<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <!-- hexo-inject:begin --><!-- hexo-inject:end --><meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 4.2.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"yao_yu.gitee.io","root":"/","scheme":"Muse","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}}};
  </script>

  <meta property="og:type" content="website">
<meta property="og:title" content="大师之路">
<meta property="og:url" content="https://yao_yu.gitee.io/index.html">
<meta property="og:site_name" content="大师之路">
<meta property="og:locale" content="zh_CN">
<meta property="article:author" content="老树">
<meta name="twitter:card" content="summary">

<link rel="canonical" href="https://yao_yu.gitee.io/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : true,
    isPost : false,
    lang   : 'zh-CN'
  };
</script>

  <title>大师之路</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript><!-- hexo-inject:begin --><link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.11.1/katex.min.css'><!-- hexo-inject:end -->

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <!-- hexo-inject:begin --><!-- hexo-inject:end --><div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">大师之路</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content index posts-expand">
            
      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://yao_yu.gitee.io/2020/05/12/hexo%E4%BD%BF%E7%94%A8%E5%B0%8F%E7%BB%93/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="老树">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="大师之路">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2020/05/12/hexo%E4%BD%BF%E7%94%A8%E5%B0%8F%E7%BB%93/" class="post-title-link" itemprop="url">hexo使用小结</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2020-05-12 17:36:28 / 修改时间：17:39:26" itemprop="dateCreated datePublished" datetime="2020-05-12T17:36:28+08:00">2020-05-12</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1>Hexo使用小结</h1>
<h2 id="一、安装">一、安装</h2>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ npm install -g hexo-cli</span><br></pre></td></tr></table></figure>
<h2 id="二、建站">二、建站</h2>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ hexo init &lt;folder&gt;</span><br><span class="line">$ cd &lt;folder&gt;</span><br><span class="line">$ npm install</span><br></pre></td></tr></table></figure>
<p>修改<code>hexo</code>站根目录下的<code>_config.yml</code>文件：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 设置站点属性</span></span><br><span class="line"><span class="attr">title:</span> <span class="string">大师之路</span></span><br><span class="line"><span class="attr">subtitle:</span> <span class="string">''</span></span><br><span class="line"><span class="attr">description:</span> <span class="string">''</span></span><br><span class="line"><span class="attr">keywords:</span></span><br><span class="line"><span class="attr">author:</span> <span class="string">老树</span></span><br><span class="line"><span class="attr">language:</span> <span class="string">zh-CN</span></span><br><span class="line"><span class="attr">timezone:</span> <span class="string">''</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># URL</span></span><br><span class="line"><span class="attr">url:</span> <span class="string">https://yao_yu.gitee.io</span></span><br><span class="line"><span class="attr">root:</span> <span class="string">/</span></span><br></pre></td></tr></table></figure>
<h2 id="三、使用NexT主题">三、使用NexT主题</h2>
<p><a href="http://theme-next.iissnan.com/getting-started.html" target="_blank" rel="noopener">NexT主题</a></p>
<h4 id="下载主题">下载主题</h4>
<p><a href="https://github.com/theme-next/hexo-theme-next" target="_blank" rel="noopener">Next(6,7)稳定版</a></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ cd hexo</span><br><span class="line">$ git clone https:&#x2F;&#x2F;github.com&#x2F;theme-next&#x2F;hexo-theme-next themes&#x2F;hexo-theme-next</span><br></pre></td></tr></table></figure>
<h4 id="启用主题">启用主题</h4>
<p>修改<code>hexo</code>站根目录下的<code>_config.yml</code>文件：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">theme:</span> <span class="string">hexo-theme-next</span></span><br></pre></td></tr></table></figure>
<h2 id="四、启用Katex">四、启用Katex</h2>
<h3 id="1-卸载默认渲染引擎">1. 卸载默认渲染引擎</h3>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm uninstall hexo-renderer-marked –save</span><br></pre></td></tr></table></figure>
<h3 id="2-安装新渲染引擎和katex引擎">2. 安装新渲染引擎和katex引擎</h3>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-renderer-markdown-it --save</span><br><span class="line">npm install markdown-it-katex --save</span><br></pre></td></tr></table></figure>
<h3 id="3-引擎设置">3. 引擎设置</h3>
<p>修改<code>hexo</code>站根目录下的<code>_config.yml</code>文件：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Markdown-it config</span></span><br><span class="line"><span class="comment">## Docs: https://github.com/celsomiranda/hexo-renderer-markdown-it/wiki/</span></span><br><span class="line"><span class="attr">markdown:</span></span><br><span class="line">  <span class="attr">render:</span></span><br><span class="line">    <span class="attr">html:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">xhtmlOut:</span> <span class="literal">false</span></span><br><span class="line">    <span class="attr">breaks:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">linkify:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">typographer:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">quotes:</span> <span class="string">'“”‘’'</span></span><br><span class="line">  <span class="attr">plugins:</span></span><br><span class="line">  <span class="attr">anchors:</span></span><br><span class="line">    <span class="attr">level:</span> <span class="number">2</span></span><br><span class="line">    <span class="attr">collisionSuffix:</span> <span class="string">''</span></span><br><span class="line"></span><br><span class="line"><span class="attr">math:</span></span><br><span class="line">  <span class="attr">engine:</span> <span class="string">'katex'</span>   </span><br><span class="line">  <span class="attr">katex:</span></span><br><span class="line">    <span class="attr">css:</span> <span class="string">https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.11.1/katex.min.css</span></span><br><span class="line">    <span class="attr">js:</span> <span class="string">https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.11.1/katex.min.js</span></span><br><span class="line">    <span class="attr">config:</span></span><br><span class="line">      <span class="comment"># KaTeX config</span></span><br><span class="line">      <span class="attr">throwOnError:</span> <span class="literal">false</span></span><br><span class="line">      <span class="attr">errorColor:</span> <span class="string">"#cc0000"</span></span><br></pre></td></tr></table></figure>
<h3 id="4-开启NexT主题math支持">4. 开启NexT主题math支持</h3>
<p>修改<code>NexT主题</code>配置<code>_config.yml</code>文件：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Math Formulas Render Support</span></span><br><span class="line"><span class="attr">math:</span></span><br><span class="line">  <span class="comment"># Default (true) will load mathjax / katex script on demand.</span></span><br><span class="line">  <span class="comment"># That is it only render those page which has `mathjax: true` in Front-matter.</span></span><br><span class="line">  <span class="comment"># If you set it to false, it will load mathjax / katex srcipt EVERY PAGE.</span></span><br><span class="line">  <span class="attr">per_page:</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line">  <span class="comment"># hexo-renderer-pandoc (or hexo-renderer-kramed) required for full MathJax support.</span></span><br><span class="line">  <span class="attr">mathjax:</span></span><br><span class="line">    <span class="attr">enable:</span> <span class="literal">false</span></span><br><span class="line">    <span class="comment"># See: https://mhchem.github.io/MathJax-mhchem/</span></span><br><span class="line">    <span class="attr">mhchem:</span> <span class="literal">false</span></span><br><span class="line"></span><br><span class="line">  <span class="comment"># hexo-renderer-markdown-it-plus (or hexo-renderer-markdown-it with markdown-it-katex plugin) required for full Katex support.</span></span><br><span class="line">  <span class="attr">katex:</span></span><br><span class="line">    <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">    <span class="comment"># See: https://github.com/KaTeX/KaTeX/tree/master/contrib/copy-tex</span></span><br><span class="line">    <span class="attr">copy_tex:</span> <span class="literal">false</span></span><br></pre></td></tr></table></figure>
<h2 id="五、调试">五、调试</h2>
<h3 id="1-生成静态文件">1. 生成静态文件</h3>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ hexo generate</span><br><span class="line">或</span><br><span class="line">$ hexo g</span><br></pre></td></tr></table></figure>
<h3 id="2-本地运行">2. 本地运行</h3>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ hexo server</span><br><span class="line">或</span><br><span class="line">$ hexo s</span><br></pre></td></tr></table></figure>
<h3 id="3-手动发布">3. 手动发布</h3>
<p>将<code>hexo\public</code>目录下的文件手动拷贝到发布git仓库，这样不会删除仓库里的内容</p>
<h2 id="帮助文档">帮助文档</h2>
<p><a href="https://hexo.io/docs/" target="_blank" rel="noopener">英文官网</a></p>
<p><a href="https://hexo.io/zh-cn/docs/" target="_blank" rel="noopener">中文帮助</a></p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://yao_yu.gitee.io/2020/05/12/%E6%A0%87%E5%87%86%E5%8D%95%E4%BD%8D%E5%90%91%E9%87%8F%E4%B8%8E%E5%9F%BA%E7%A1%80%E7%9F%A9%E9%98%B5/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="老树">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="大师之路">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2020/05/12/%E6%A0%87%E5%87%86%E5%8D%95%E4%BD%8D%E5%90%91%E9%87%8F%E4%B8%8E%E5%9F%BA%E7%A1%80%E7%9F%A9%E9%98%B5/" class="post-title-link" itemprop="url">标准单位向量与基础矩阵</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2020-05-12 15:06:36 / 修改时间：16:22:35" itemprop="dateCreated datePublished" datetime="2020-05-12T15:06:36+08:00">2020-05-12</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h3 id="2-2-1-标准单位向量与基础矩阵">2.2.1 标准单位向量与基础矩阵</h3>
<p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathdefault">n</span></span></span></span>维标准单位列向量是指下列<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathdefault">n</span></span></span></span>个<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathdefault">n</span></span></span></span>维列向量：</p>
<p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>1</mn></msub><mo>=</mo><mrow><mo fence="true">(</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi><mi mathvariant="normal">⋮</mi><mpadded height="+0em" voffset="0em"><mspace mathbackground="black" width="0em" height="1.5em"></mspace></mpadded></mi></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr></mtable><mo fence="true">)</mo></mrow><mo separator="true">,</mo><msub><mi>e</mi><mn>2</mn></msub><mo>=</mo><mrow><mo fence="true">(</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi><mi mathvariant="normal">⋮</mi><mpadded height="+0em" voffset="0em"><mspace mathbackground="black" width="0em" height="1.5em"></mspace></mpadded></mi></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr></mtable><mo fence="true">)</mo></mrow><mo separator="true">,</mo><mo>⋯</mo><mtext> </mtext><mo separator="true">,</mo><msub><mi>e</mi><mi>n</mi></msub><mo>=</mo><mrow><mo fence="true">(</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi><mi mathvariant="normal">⋮</mi><mpadded height="+0em" voffset="0em"><mspace mathbackground="black" width="0em" height="1.5em"></mspace></mpadded></mi></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd></mtr></mtable><mo fence="true">)</mo></mrow></mrow><annotation encoding="application/x-tex">e_1 = \begin{pmatrix}1 \\ 0 \\ \vdots \\ 0\end{pmatrix},e_2 = \begin{pmatrix}0 \\ 1 \\ \vdots \\ 0\end{pmatrix},\cdots,e_n = \begin{pmatrix}0 \\ 0 \\ \vdots \\ 1\end{pmatrix}
</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.58056em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathdefault">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:5.459999999999999em;vertical-align:-2.4799999999999995em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.950035em;"><span style="top:-1.3499850000000007em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎝</span></span></span><span style="top:-2.4999950000000006em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎜</span></span></span><span style="top:-3.0950050000000005em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎜</span></span></span><span style="top:-3.6900150000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎜</span></span></span><span style="top:-3.7100150000000007em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎜</span></span></span><span style="top:-4.950035000000001em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎛</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.4500349999999997em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.9799999999999995em;"><span style="top:-5.8275em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-4.6275em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-2.7674999999999996em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord">⋮</span><span class="mord rule" style="border-right-width:0em;border-top-width:1.5em;bottom:0em;"></span></span></span></span><span style="top:-1.5675000000000006em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.4799999999999995em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.950035em;"><span style="top:-1.3499850000000007em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎠</span></span></span><span style="top:-2.4999950000000006em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎟</span></span></span><span style="top:-3.0950050000000005em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎟</span></span></span><span style="top:-3.6900150000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎟</span></span></span><span style="top:-3.7100150000000007em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎟</span></span></span><span style="top:-4.950035000000001em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎞</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.4500349999999997em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathdefault">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:5.459999999999999em;vertical-align:-2.4799999999999995em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.950035em;"><span style="top:-1.3499850000000007em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎝</span></span></span><span style="top:-2.4999950000000006em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎜</span></span></span><span style="top:-3.0950050000000005em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎜</span></span></span><span style="top:-3.6900150000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎜</span></span></span><span style="top:-3.7100150000000007em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎜</span></span></span><span style="top:-4.950035000000001em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎛</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.4500349999999997em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.9799999999999995em;"><span style="top:-5.8275em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-4.6275em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-2.7674999999999996em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord">⋮</span><span class="mord rule" style="border-right-width:0em;border-top-width:1.5em;bottom:0em;"></span></span></span></span><span style="top:-1.5675000000000006em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.4799999999999995em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.950035em;"><span style="top:-1.3499850000000007em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎠</span></span></span><span style="top:-2.4999950000000006em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎟</span></span></span><span style="top:-3.0950050000000005em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎟</span></span></span><span style="top:-3.6900150000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎟</span></span></span><span style="top:-3.7100150000000007em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎟</span></span></span><span style="top:-4.950035000000001em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎞</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.4500349999999997em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathdefault">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:5.459999999999999em;vertical-align:-2.4799999999999995em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.950035em;"><span style="top:-1.3499850000000007em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎝</span></span></span><span style="top:-2.4999950000000006em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎜</span></span></span><span style="top:-3.0950050000000005em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎜</span></span></span><span style="top:-3.6900150000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎜</span></span></span><span style="top:-3.7100150000000007em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎜</span></span></span><span style="top:-4.950035000000001em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎛</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.4500349999999997em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.9799999999999995em;"><span style="top:-5.8275em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-4.6275em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-2.7674999999999996em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord">⋮</span><span class="mord rule" style="border-right-width:0em;border-top-width:1.5em;bottom:0em;"></span></span></span></span><span style="top:-1.5675000000000006em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.4799999999999995em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.950035em;"><span style="top:-1.3499850000000007em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎠</span></span></span><span style="top:-2.4999950000000006em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎟</span></span></span><span style="top:-3.0950050000000005em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎟</span></span></span><span style="top:-3.6900150000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎟</span></span></span><span style="top:-3.7100150000000007em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎟</span></span></span><span style="top:-4.950035000000001em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎞</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.4500349999999997em;"><span></span></span></span></span></span></span></span></span></span></span></span></p>
<p>向量组<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>e</mi><mn>1</mn><mi>T</mi></msubsup><mo separator="true">,</mo><msubsup><mi>e</mi><mn>2</mn><mi>T</mi></msubsup><mo separator="true">,</mo><mo>⋯</mo><mtext> </mtext><msubsup><mi>e</mi><mi>n</mi><mi>T</mi></msubsup></mrow><annotation encoding="application/x-tex">e_1^T,e_2^T,\cdots\,e_n^T</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0894389999999998em;vertical-align:-0.24810799999999997em;"></span><span class="mord"><span class="mord mathdefault">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8413309999999999em;"><span style="top:-2.4518920000000004em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.24810799999999997em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathdefault">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8413309999999999em;"><span style="top:-2.4518920000000004em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.24810799999999997em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathdefault">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8413309999999999em;"><span style="top:-2.4530000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">n</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span>则被称为<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathdefault">n</span></span></span></span>维标准单位行向量，标准单位向量有下列基本性质：</p>
<ol>
<li>若<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mo mathvariant="normal">≠</mo><mi>j</mi></mrow><annotation encoding="application/x-tex">i \neq j</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="mord mathdefault">i</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel"><span class="mrel"><span class="mord"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.69444em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="rlap"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="inner"><span class="mrel"></span></span><span class="fix"></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.19444em;"><span></span></span></span></span></span></span><span class="mrel">=</span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.85396em;vertical-align:-0.19444em;"></span><span class="mord mathdefault" style="margin-right:0.05724em;">j</span></span></span></span>，则<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>e</mi><mi>i</mi><mi>T</mi></msubsup><msub><mi>e</mi><mi>j</mi></msub><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">e_i^Te_j=0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.1274389999999999em;vertical-align:-0.286108em;"></span><span class="mord"><span class="mord mathdefault">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8413309999999999em;"><span style="top:-2.441336em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">i</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.258664em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathdefault">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.311664em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">0</span></span></span></span>，而<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>e</mi><mi>i</mi><mi>T</mi></msubsup><msub><mi>e</mi><mi>i</mi></msub><mo>=</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">e_i^Te_i=1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0999949999999998em;vertical-align:-0.258664em;"></span><span class="mord"><span class="mord mathdefault">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8413309999999999em;"><span style="top:-2.441336em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">i</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.258664em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathdefault">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.31166399999999994em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">1</span></span></span></span>；</li>
<li>若<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo>=</mo><mo stretchy="false">(</mo><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><msub><mo stretchy="false">)</mo><mrow><mi>m</mi><mo>×</mo><mi>n</mi></mrow></msub></mrow><annotation encoding="application/x-tex">A=(a_{ij})_{m\times n}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathdefault">A</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.036108em;vertical-align:-0.286108em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathdefault">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.311664em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.25833100000000003em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">m</span><span class="mbin mtight">×</span><span class="mord mathdefault mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.208331em;"><span></span></span></span></span></span></span></span></span></span>，则<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><msub><mi>e</mi><mi>i</mi></msub></mrow><annotation encoding="application/x-tex">Ae_i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord mathdefault">A</span><span class="mord"><span class="mord mathdefault">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.31166399999999994em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>是<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi></mrow><annotation encoding="application/x-tex">A</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathdefault">A</span></span></span></span>的第<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi></mrow><annotation encoding="application/x-tex">i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.65952em;vertical-align:0em;"></span><span class="mord mathdefault">i</span></span></span></span>个列向量, <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>e</mi><mi>i</mi><mi>T</mi></msubsup><mi>A</mi></mrow><annotation encoding="application/x-tex">e_i^TA</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0999949999999998em;vertical-align:-0.258664em;"></span><span class="mord"><span class="mord mathdefault">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8413309999999999em;"><span style="top:-2.441336em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">i</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.258664em;"><span></span></span></span></span></span></span><span class="mord mathdefault">A</span></span></span></span>是<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi></mrow><annotation encoding="application/x-tex">A</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathdefault">A</span></span></span></span>的第<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi></mrow><annotation encoding="application/x-tex">i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.65952em;vertical-align:0em;"></span><span class="mord mathdefault">i</span></span></span></span>个行向量;</li>
<li>若<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo>=</mo><mo stretchy="false">(</mo><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><msub><mo stretchy="false">)</mo><mrow><mi>m</mi><mo>×</mo><mi>n</mi></mrow></msub></mrow><annotation encoding="application/x-tex">A=(a_{ij})_{m\times n}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathdefault">A</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.036108em;vertical-align:-0.286108em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathdefault">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.311664em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.25833100000000003em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">m</span><span class="mbin mtight">×</span><span class="mord mathdefault mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.208331em;"><span></span></span></span></span></span></span></span></span></span>，则<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>e</mi><mi>i</mi><mi>T</mi></msubsup><mi>A</mi><msub><mi>e</mi><mi>j</mi></msub><mo>=</mo><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mrow><annotation encoding="application/x-tex">e_i^TAe_j=a_{ij}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.1274389999999999em;vertical-align:-0.286108em;"></span><span class="mord"><span class="mord mathdefault">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8413309999999999em;"><span style="top:-2.441336em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">i</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.258664em;"><span></span></span></span></span></span></span><span class="mord mathdefault">A</span><span class="mord"><span class="mord mathdefault">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.311664em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.716668em;vertical-align:-0.286108em;"></span><span class="mord"><span class="mord mathdefault">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.311664em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span></span></span></span>.</li>
</ol>
<p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathdefault">n</span></span></span></span>阶基础矩阵(又称初级矩阵)是指<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>n</mi><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">n^2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8141079999999999em;vertical-align:0em;"></span><span class="mord"><span class="mord mathdefault">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141079999999999em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span>个<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathdefault">n</span></span></span></span>阶矩阵<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>E</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo stretchy="false">(</mo><mi>i</mi><mo separator="true">,</mo><mi>j</mi><mo>=</mo><mn>1</mn><mo separator="true">,</mo><mn>2</mn><mo separator="true">,</mo><mo>⋯</mo><mtext> </mtext><mo separator="true">,</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">{E_{ij}(i,j=1,2,\cdots,n)}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.036108em;vertical-align:-0.286108em;"></span><span class="mord"><span class="mord"><span class="mord mathdefault" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.311664em;"><span style="top:-2.5500000000000003em;margin-left:-0.05764em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathdefault">i</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathdefault" style="margin-right:0.05724em;">j</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathdefault">n</span><span class="mclose">)</span></span></span></span></span>.这里<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>E</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mrow><annotation encoding="application/x-tex">E_{ij}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.969438em;vertical-align:-0.286108em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.311664em;"><span style="top:-2.5500000000000003em;margin-left:-0.05764em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span></span></span></span>是一个<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathdefault">n</span></span></span></span>阶矩阵，它的第<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>i</mi><mo separator="true">,</mo><mi>j</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(i,j)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathdefault">i</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathdefault" style="margin-right:0.05724em;">j</span><span class="mclose">)</span></span></span></span>元素等于<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn></mrow><annotation encoding="application/x-tex">1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">1</span></span></span></span>，其他元素全为<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn></mrow><annotation encoding="application/x-tex">0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">0</span></span></span></span>. 基础矩阵也可以看成是标准单位向量的积:</p>
<p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>E</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msub><mi>e</mi><mi>i</mi></msub><msubsup><mi>e</mi><mi>j</mi><mi>T</mi></msubsup></mrow><annotation encoding="application/x-tex">E_{ij} = e_ie_j^T
</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.969438em;vertical-align:-0.286108em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.311664em;"><span style="top:-2.5500000000000003em;margin-left:-0.05764em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.274439em;vertical-align:-0.383108em;"></span><span class="mord"><span class="mord mathdefault">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.31166399999999994em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathdefault">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.891331em;"><span style="top:-2.4530000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.05724em;">j</span></span></span><span style="top:-3.1130000000000004em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.383108em;"><span></span></span></span></span></span></span></span></span></span></span></p>
<p>由此, 我们不难证明基础矩阵的下列性质:</p>
<ol>
<li>若<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>j</mi><mo mathvariant="normal">≠</mo><mi>k</mi></mrow><annotation encoding="application/x-tex">j\neq k</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="mord mathdefault" style="margin-right:0.05724em;">j</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel"><span class="mrel"><span class="mord"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.69444em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="rlap"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="inner"><span class="mrel"></span></span><span class="fix"></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.19444em;"><span></span></span></span></span></span></span><span class="mrel">=</span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathdefault" style="margin-right:0.03148em;">k</span></span></span></span>, 则<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>E</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><msub><mi>E</mi><mrow><mi>k</mi><mi>l</mi></mrow></msub><mo>=</mo><mi>O</mi></mrow><annotation encoding="application/x-tex">E_{ij}E_{kl}=O</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.969438em;vertical-align:-0.286108em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.311664em;"><span style="top:-2.5500000000000003em;margin-left:-0.05764em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:-0.05764em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right:0.03148em;">k</span><span class="mord mathdefault mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathdefault" style="margin-right:0.02778em;">O</span></span></span></span>;</li>
<li>若<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>j</mi><mo>=</mo><mi>k</mi></mrow><annotation encoding="application/x-tex">j= k</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.85396em;vertical-align:-0.19444em;"></span><span class="mord mathdefault" style="margin-right:0.05724em;">j</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathdefault" style="margin-right:0.03148em;">k</span></span></span></span>, 则<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>E</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><msub><mi>E</mi><mrow><mi>k</mi><mi>l</mi></mrow></msub><mo>=</mo><msub><mi>E</mi><mrow><mi>i</mi><mi>l</mi></mrow></msub></mrow><annotation encoding="application/x-tex">E_{ij}E_{kl}=E_{il}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.969438em;vertical-align:-0.286108em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.311664em;"><span style="top:-2.5500000000000003em;margin-left:-0.05764em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:-0.05764em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right:0.03148em;">k</span><span class="mord mathdefault mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:-0.05764em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>;</li>
<li>若<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi></mrow><annotation encoding="application/x-tex">A</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathdefault">A</span></span></span></span>是<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathdefault">n</span></span></span></span>阶矩阵且<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo>=</mo><mo stretchy="false">(</mo><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">A=(a_{ij})</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathdefault">A</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.036108em;vertical-align:-0.286108em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathdefault">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.311664em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>, 则</li>
</ol>
<p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo>=</mo><munderover><mo>∑</mo><mrow><mi>i</mi><mo separator="true">,</mo><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mi>n</mi></munderover><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><msub><mi>E</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mrow><annotation encoding="application/x-tex">A=\sum_{i,j=1}^{n}a_{ij}E_{ij}
</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathdefault">A</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:3.0651740000000007em;vertical-align:-1.4137769999999998em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6513970000000007em;"><span style="top:-1.872331em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mpunct mtight">,</span><span class="mord mathdefault mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.050005em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3000050000000005em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4137769999999998em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathdefault">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.311664em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.311664em;"><span style="top:-2.5500000000000003em;margin-left:-0.05764em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span></span></span></span></span></p>
<ol start="4">
<li>若<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi></mrow><annotation encoding="application/x-tex">A</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathdefault">A</span></span></span></span>是<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathdefault">n</span></span></span></span>阶矩阵且<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo>=</mo><mo stretchy="false">(</mo><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">A=(a_{ij})</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathdefault">A</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.036108em;vertical-align:-0.286108em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathdefault">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.311664em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>, 则<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>E</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mi>A</mi></mrow><annotation encoding="application/x-tex">E_{ij}A</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.969438em;vertical-align:-0.286108em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.311664em;"><span style="top:-2.5500000000000003em;margin-left:-0.05764em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span><span class="mord mathdefault">A</span></span></span></span>将<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi></mrow><annotation encoding="application/x-tex">A</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathdefault">A</span></span></span></span>的第<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>j</mi></mrow><annotation encoding="application/x-tex">j</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.85396em;vertical-align:-0.19444em;"></span><span class="mord mathdefault" style="margin-right:0.05724em;">j</span></span></span></span>行变为第<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi></mrow><annotation encoding="application/x-tex">i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.65952em;vertical-align:0em;"></span><span class="mord mathdefault">i</span></span></span></span>行, 将其他元素全变为<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn></mrow><annotation encoding="application/x-tex">0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">0</span></span></span></span>;</li>
<li>若<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi></mrow><annotation encoding="application/x-tex">A</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathdefault">A</span></span></span></span>是<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathdefault">n</span></span></span></span>阶矩阵且<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo>=</mo><mo stretchy="false">(</mo><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">A=(a_{ij})</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathdefault">A</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.036108em;vertical-align:-0.286108em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathdefault">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.311664em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>, 则<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><msub><mi>E</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mrow><annotation encoding="application/x-tex">AE_{ij}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.969438em;vertical-align:-0.286108em;"></span><span class="mord mathdefault">A</span><span class="mord"><span class="mord mathdefault" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.311664em;"><span style="top:-2.5500000000000003em;margin-left:-0.05764em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span></span></span></span>将<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi></mrow><annotation encoding="application/x-tex">A</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathdefault">A</span></span></span></span>的第<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi></mrow><annotation encoding="application/x-tex">i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.65952em;vertical-align:0em;"></span><span class="mord mathdefault">i</span></span></span></span>列变为第<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>j</mi></mrow><annotation encoding="application/x-tex">j</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.85396em;vertical-align:-0.19444em;"></span><span class="mord mathdefault" style="margin-right:0.05724em;">j</span></span></span></span>列, 将其他元素全变为<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn></mrow><annotation encoding="application/x-tex">0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">0</span></span></span></span>;</li>
</ol>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://yao_yu.gitee.io/2020/05/12/CMake%20install%E5%91%BD%E4%BB%A4/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="老树">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="大师之路">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2020/05/12/CMake%20install%E5%91%BD%E4%BB%A4/" class="post-title-link" itemprop="url">CMake install命令</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2020-05-12 12:06:24 / 修改时间：12:05:42" itemprop="dateCreated datePublished" datetime="2020-05-12T12:06:24+08:00">2020-05-12</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="CMake-install"><a href="#CMake-install" class="headerlink" title="CMake install"></a>CMake install</h1><p><code>install</code>命令用于指定安装时规则</p>
<h2 id="语法"><a href="#语法" class="headerlink" title="语法"></a>语法</h2><figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">install</span>(TARGETS &lt;<span class="keyword">target</span>&gt;... [...])</span><br><span class="line"><span class="keyword">install</span>(&#123;FILES | PROGRAMS&#125; &lt;<span class="keyword">file</span>&gt;... [...])</span><br><span class="line"><span class="keyword">install</span>(DIRECTORY &lt;dir&gt;... [...])</span><br><span class="line"><span class="keyword">install</span>(SCRIPT &lt;<span class="keyword">file</span>&gt; [...])</span><br><span class="line"><span class="keyword">install</span>(CODE &lt;code&gt; [...])</span><br><span class="line"><span class="keyword">install</span>(<span class="keyword">EXPORT</span> &lt;<span class="keyword">export</span>-name&gt; [...])</span><br></pre></td></tr></table></figure>

<h2 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h2><p>本命令为项目生成安装规则。在同一个源目录内的规则按顺序执行，跨目录没有定义安装顺序。</p>
<h2 id="安装目标"><a href="#安装目标" class="headerlink" title="安装目标"></a>安装目标</h2><figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">install</span>(TARGETS targets... [<span class="keyword">EXPORT</span> &lt;<span class="keyword">export</span>-name&gt;]</span><br><span class="line">        [[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE|</span><br><span class="line">          PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE]</span><br><span class="line">         [DESTINATION &lt;dir&gt;]</span><br><span class="line">         [PERMISSIONS permissions...]</span><br><span class="line">         [CONFIGURATIONS [Debug|Release|...]]</span><br><span class="line">         [COMPONENT &lt;component&gt;]</span><br><span class="line">         [NAMELINK_COMPONENT &lt;component&gt;]</span><br><span class="line">         [OPTIONAL] [EXCLUDE_FROM_ALL]</span><br><span class="line">         [NAMELINK_ONLY|NAMELINK_SKIP]</span><br><span class="line">        ] [...]</span><br><span class="line">        [INCLUDES DESTINATION [&lt;dir&gt; ...]]</span><br><span class="line">        )</span><br></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th><strong>Target Type</strong></th>
<th><strong>GNUInstallDirs Variable</strong></th>
<th><strong>Built-In Default</strong></th>
</tr>
</thead>
<tbody><tr>
<td>RUNTIME</td>
<td>${CMAKE_INSTALL_BINDIR}</td>
<td>bin</td>
</tr>
<tr>
<td>LIBRARY</td>
<td>${CMAKE_INSTALL_LIBDIR}</td>
<td>lib</td>
</tr>
<tr>
<td>ARCHIVE</td>
<td>${CMAKE_INSTALL_LIBDIR}</td>
<td>lib</td>
</tr>
<tr>
<td>PRIVATE_HEADER</td>
<td>${CMAKE_INSTALL_INCLUDEDIR}</td>
<td>include</td>
</tr>
<tr>
<td>PUBLIC_HEADER</td>
<td>${CMAKE_INSTALL_INCLUDEDIR}</td>
<td>include</td>
</tr>
</tbody></table>
<h2 id="安装文件"><a href="#安装文件" class="headerlink" title="安装文件"></a>安装文件</h2><figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">install</span>(&lt;FILES|PROGRAMS&gt; files...</span><br><span class="line">        TYPE &lt;type&gt; | DESTINATION &lt;dir&gt;</span><br><span class="line">        [PERMISSIONS permissions...]</span><br><span class="line">        [CONFIGURATIONS [Debug|Release|...]]</span><br><span class="line">        [COMPONENT &lt;component&gt;]</span><br><span class="line">        [RENAME &lt;name&gt;] [OPTIONAL] [EXCLUDE_FROM_ALL])</span><br></pre></td></tr></table></figure>

<p><code>FILE</code>参数为项目中文件安装指定了规则。相对路径是指相对于当前源目录。如果不指定<code>PERMISSIONS</code>参数，则安装文件的默认权限为<code>OWNER_WRITE</code>、<code>OWNER_READ</code>、<code>GROUP_READ</code>和<code>WORLD_READ</code>。</p>
<p><code>PROGRAM</code>参数除了包括<code>FILE</code>参数功能与权限外，还有<code>OWNER_EXECUTE</code>, <code>GROUP_EXECUTE</code>和<code>WORLD_EXECUTE</code>权限。它用于安装没有目标的执行程序，比如脚本。</p>
<p>必须提供<code>TYPE</code>或<code>DESTINATION</code>，但不能同时提供。</p>
<table>
<thead>
<tr>
<th><strong>Type Argument</strong></th>
<th><strong>GNUInstallDirs Variable</strong></th>
<th><strong>Built-In Default</strong></th>
</tr>
</thead>
<tbody><tr>
<td>RUNTIME</td>
<td>${CMAKE_INSTALL_BINDIR}</td>
<td>bin</td>
</tr>
<tr>
<td>SBIN</td>
<td>${CMAKE_INSTALL_SBINDIR}</td>
<td>sbin</td>
</tr>
<tr>
<td>LIB</td>
<td>${CMAKE_INSTALL_LIBDIR}</td>
<td>lib</td>
</tr>
<tr>
<td>INCLUDE</td>
<td>${CMAKE_INSTALL_INCLUDEDIR}</td>
<td>include</td>
</tr>
<tr>
<td>SYSCONF</td>
<td>${CMAKE_INSTALL_SYSCONFDIR}</td>
<td>etc</td>
</tr>
<tr>
<td>SHAREDSTATE</td>
<td>${CMAKE_INSTALL_SHARESTATEDIR}</td>
<td>com</td>
</tr>
<tr>
<td>LOCALSTATE</td>
<td>${CMAKE_INSTALL_LOCALSTATEDIR}</td>
<td>var</td>
</tr>
<tr>
<td>RUNSTATE</td>
<td>${CMAKE_INSTALL_RUNSTATEDIR}</td>
<td><code>&lt;LOCALSTATE dir&gt;/run</code></td>
</tr>
<tr>
<td>DATA</td>
<td>${CMAKE_INSTALL_DATADIR}</td>
<td><code>&lt;DATAROOT dir&gt;</code></td>
</tr>
<tr>
<td>INFO</td>
<td>${CMAKE_INSTALL_INFODIR}</td>
<td><code>&lt;DATAROOT dir&gt;/info</code></td>
</tr>
<tr>
<td>LOCALE</td>
<td>${CMAKE_INSTALL_LOCALEDIR}</td>
<td><code>&lt;DATAROOT dir&gt;/locale</code></td>
</tr>
<tr>
<td>MAN</td>
<td>${CMAKE_INSTALL_MANDIR}</td>
<td><code>&lt;DATAROOT dir&gt;/man</code></td>
</tr>
<tr>
<td>DOC</td>
<td>${CMAKE_INSTALL_DOCDIR}</td>
<td><code>&lt;DATAROOT dir&gt;/doc</code></td>
</tr>
</tbody></table>
<p>示例：</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">include</span>(GNUInstallDirs)</span><br><span class="line"><span class="keyword">install</span>(FILES mylib.h</span><br><span class="line">        DESTINATION <span class="variable">$&#123;CMAKE_INSTALL_INCLUDEDIR&#125;</span>/myproj</span><br><span class="line">)</span><br></pre></td></tr></table></figure>



<h2 id="安装目录"><a href="#安装目录" class="headerlink" title="安装目录"></a>安装目录</h2><figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">install</span>(DIRECTORY dirs...</span><br><span class="line">        TYPE &lt;type&gt; | DESTINATION &lt;dir&gt;</span><br><span class="line">        [FILE_PERMISSIONS permissions...]</span><br><span class="line">        [DIRECTORY_PERMISSIONS permissions...]</span><br><span class="line">        [USE_SOURCE_PERMISSIONS] [OPTIONAL] [MESSAGE_NEVER]</span><br><span class="line">        [CONFIGURATIONS [Debug|Release|...]]</span><br><span class="line">        [COMPONENT &lt;component&gt;] [EXCLUDE_FROM_ALL]</span><br><span class="line">        [FILES_MATCHING]</span><br><span class="line">        [[PATTERN &lt;pattern&gt; | REGEX &lt;regex&gt;]</span><br><span class="line">         [EXCLUDE] [PERMISSIONS permissions...]] [...])</span><br></pre></td></tr></table></figure>

<p><code>DIRECTORY</code>参数用于将一个或多个目录安装到指定目录。目录结构会原样复制到目标目录。每个目录名的最后一个组件被追加到目标目录，但是可以使用一个尾部斜杠来避免这种情况，因为它会使最后一个组件为空。</p>
<p>示例</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">install</span>(DIRECTORY src/ DESTINATION <span class="keyword">include</span>/myproj</span><br><span class="line">        FILES_MATCHING PATTERN <span class="string">"*.h"</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">install</span>(DIRECTORY icons scripts/ DESTINATION share/myproj</span><br><span class="line">        PATTERN <span class="string">"CVS"</span> EXCLUDE</span><br><span class="line">        PATTERN <span class="string">"scripts/*"</span></span><br><span class="line">        PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ</span><br><span class="line">                    GROUP_EXECUTE GROUP_READ)</span><br></pre></td></tr></table></figure>
      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://yao_yu.gitee.io/2020/05/11/CMake%20Tutorial(v2)/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="老树">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="大师之路">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2020/05/11/CMake%20Tutorial(v2)/" class="post-title-link" itemprop="url">CMake Tutorial(v2)</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-05-11 17:36:01" itemprop="dateCreated datePublished" datetime="2020-05-11T17:36:01+08:00">2020-05-11</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2020-05-09 17:16:11" itemprop="dateModified" datetime="2020-05-09T17:16:11+08:00">2020-05-09</time>
              </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="CMake教程CMake-Tutorial"><a href="#CMake教程CMake-Tutorial" class="headerlink" title="CMake教程CMake Tutorial"></a><a href="https://cmake.org/cmake/help/latest/guide/tutorial/index.html" target="_blank" rel="noopener">CMake教程CMake Tutorial</a></h1><p>[toc]</p>
<p>本教程一步一步的介绍了CMake帮助文档中常见的构建系统内容。通过一个样例工程解析各种内容如何协同工作，非常有助于理解CMake。教程文档和示例的源代码可以在CMake源代码树的<code>Help/guide/tutorial</code>目录中找到。每个步骤对应一个以该步骤命名的目录，教程内容都是以这些目录内的文件为基础开始的。本教程示例是渐进式的，因此每一步都为前一步提供完整的解决方案。</p>
<h2 id="第1步-基本起始点-A-Basic-Starting-Point-Step-1"><a href="#第1步-基本起始点-A-Basic-Starting-Point-Step-1" class="headerlink" title="第1步 基本起始点 A Basic Starting Point (Step 1)"></a>第1步 基本起始点 A Basic Starting Point (Step 1)</h2><p>最基本的项目是从源文件构建可执行文件。对于简单的项目，只需要一个三行<code>CMakeLists.txt</code>文件(以下省略”文件”两个字)。本教程从这里开始。在<code>Step1</code>目录中创建一个<code>CMakeLists.txt</code>，内容如下:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">cmake_minimum_required</span>(VERSION <span class="number">3.10</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置项目名称</span></span><br><span class="line"><span class="keyword">project</span>(Tutorial)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 生成可执行文件</span></span><br><span class="line"><span class="keyword">add_executable</span>(Tutorial tutorial.cxx)</span><br></pre></td></tr></table></figure>

<p>注意，本例在<code>CMakeLists.txt</code>中使用了小写命令，CMake支持大写、小写和混合大小写命令。<code>Step1</code>目录中提供了<code>tutorial.cxx</code>的源代码，它用来计算一个数字的平方根。</p>
<h3 id="1-1-添加项目版本号和配置头文件"><a href="#1-1-添加项目版本号和配置头文件" class="headerlink" title="1.1 添加项目版本号和配置头文件"></a>1.1 添加项目版本号和配置头文件</h3><p>我们要使用的第一个CMake功能是为执行文件和项目添加一个版本号。虽然可以直接在源代码中这样做，但是在<code>CMakeLists.txt</code>中配置更加灵活。</p>
<p>首先，修改<code>CMakeLists.txt</code>，使用<code>project()</code>命令设置项目名称和版本号</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">cmake_minimum_required</span>(VERSION <span class="number">3.10</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置项目名称和版本号</span></span><br><span class="line"><span class="keyword">project</span>(Tutorial VERSION <span class="number">1.0</span>)</span><br></pre></td></tr></table></figure>

<p>然后, 配置一个头文件，用于将版本号传递给源代码:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">configure_file</span>(TutorialConfig.h.in TutorialConfig.h)</span><br></pre></td></tr></table></figure>

<p>由于配置的文件会生成在编译目录<code>(${PROJECT_BINARY_DIR})</code>，我们需要将该目录添加到头文件搜索路径列表中。在<code>CMakeLists.txt</code>末尾添加以下行:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">target_include_directories</span>(Tutorial PUBLIC</span><br><span class="line">                           <span class="string">"$&#123;PROJECT_BINARY_DIR&#125;"</span></span><br><span class="line">                           )</span><br></pre></td></tr></table></figure>

<p>使用您喜欢的编辑器，在源码目录中创建<code>TutorialConfig.h.in</code>，它包含以下内容:</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// the configured options and settings for Tutorial</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@</span></span><br></pre></td></tr></table></figure>

<p>当CMake配置这个头文件时，将会替换<code>@Tutorial_VERSION_MAJOR@</code>和<code>@Tutorial_VERSION_MINOR@</code>的值。</p>
<p>再下一步，修改<code>tutorial.cxx</code>以包含配置的头文件<code>TutorialConfig.h</code>。</p>
<p>最后，我们更新 <code>tutorial.cxx</code>来打印版本号:</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (argc &lt; <span class="number">2</span>) &#123;</span><br><span class="line">    <span class="comment">// 输出版本号</span></span><br><span class="line">    <span class="built_in">std</span>::<span class="built_in">cout</span> &lt;&lt; argv[<span class="number">0</span>] &lt;&lt; <span class="string">" Version "</span> &lt;&lt; Tutorial_VERSION_MAJOR &lt;&lt; <span class="string">"."</span></span><br><span class="line">              &lt;&lt; Tutorial_VERSION_MINOR &lt;&lt; <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">    <span class="built_in">std</span>::<span class="built_in">cout</span> &lt;&lt; <span class="string">"Usage: "</span> &lt;&lt; argv[<span class="number">0</span>] &lt;&lt; <span class="string">" number"</span> &lt;&lt; <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>

<h3 id="1-2-指定C-标准"><a href="#1-2-指定C-标准" class="headerlink" title="1.2 指定C++标准"></a>1.2 指定C++标准</h3><p>接下来，我们为项目增加一点C++11特性。我们将<code>tutorial.cxx</code>中的<code>atof</code>替换为<code>std::stod</code>，同时，删除<code>#include &lt;cstdlib&gt;</code>。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="keyword">double</span> inputValue = <span class="built_in">std</span>::stod(argv[<span class="number">1</span>]);</span><br></pre></td></tr></table></figure>

<p>为了让CMake能够使用正确的标志，我们需要在CMake代码中显式地声明相应的标志。在CMake中支持特定C++标准的最简单方法是使用<code>CMAKE_CXX_STANDARD</code>变量。在本教程中，将<code>CMakeLists.txt</code>中的<code>CMAKE_CXX_STANDARD</code>变量设置为<code>11</code>，将<code>CMAKE_CXX_STANDARD_REQUIRED</code>设置为<code>True</code>:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">cmake_minimum_required</span>(VERSION <span class="number">3.10</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># set the project name and version</span></span><br><span class="line"><span class="keyword">project</span>(Tutorial VERSION <span class="number">1.0</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># specify the C++ standard</span></span><br><span class="line"><span class="keyword">set</span>(CMAKE_CXX_STANDARD <span class="number">11</span>)</span><br><span class="line"><span class="keyword">set</span>(CMAKE_CXX_STANDARD_REQUIRED <span class="keyword">True</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># add the executable</span></span><br><span class="line"><span class="keyword">add_executable</span>(Tutorial tutorial.cxx)</span><br></pre></td></tr></table></figure>

<h3 id="1-3-构建和测试"><a href="#1-3-构建和测试" class="headerlink" title="1.3 构建和测试"></a>1.3 构建和测试</h3><p>运行<code>cmake</code>可执行文件或<code>cmake-gui</code>来配置项目，然后使用您选择的构建工具构建它。</p>
<p>例如，我们可以从命令行导航到<code>CMake</code>源代码树的<code>Help/guide/tutorial/Step1</code>目录，并运行以下命令:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ mkdir build</span><br><span class="line">$ cd build</span><br><span class="line">$ cmake ..</span><br><span class="line">$ cmake --build .</span><br></pre></td></tr></table></figure>

<p>运行编译结果目录(可能是make目录或Debug或Release子目录)的执行程序，<code>win10</code>示例如下:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">PS build&gt; Debug\Tutorial.exe 4294967296</span><br><span class="line">The square root of 4.29497e+09 is 65536</span><br><span class="line">PS build&gt; Debug\Tutorial.exe 10</span><br><span class="line">The square root of 10 is 3.16228</span><br><span class="line">PS build&gt; Debug\Tutorial.exe</span><br><span class="line">xxx\Debug\Tutorial.exe number</span><br></pre></td></tr></table></figure>


<h2 id="第2步-生成库-Adding-a-Library-Step-2"><a href="#第2步-生成库-Adding-a-Library-Step-2" class="headerlink" title="第2步 生成库 Adding a Library (Step 2)"></a>第2步 生成库 Adding a Library (Step 2)</h2><p>现在，我们将在项目中添加一个包含计算平方根功能的库。最终生成的可执行文件<strong>可以</strong>使用这个库而不是使用标准数学库中的函数。</p>
<p>在本教程中，我们将把这个库放在子目录<code>MathFunctions</code>中，这个目录已包含一个头文件<code>MathFunctions.h</code>和一个源文件<code>mysqrt.cxx</code>。源文件中有一个名为<code>mysqrt</code>的函数，它提供了与编译器的sqrt函数类似的功能。</p>
<p>将下一行添加到<code>MathFunctions</code>目录下的<code>CMakeLists.txt</code>:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">add_library</span>(MathFunctions mysqrt.cxx)</span><br></pre></td></tr></table></figure>

<p>为了利用这个新库，我们需要在顶层<code>CMakeLists.txt</code>中添加<code>add_subdirectory()</code>命令，该命令会构建<code>MathFunctions</code>库。接着，我们将新库添加到可执行文件中，并将<code>MathFunctions</code>添加到头文件搜索路径，以便可以找到<code>mqsqrt.h</code>头文件。顶层<code>CMakeLists.txt</code>的末尾现在应该是这样的:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># add the MathFunctions library</span></span><br><span class="line"><span class="keyword">add_subdirectory</span>(MathFunctions)</span><br><span class="line"></span><br><span class="line"><span class="comment"># add the executable</span></span><br><span class="line"><span class="keyword">add_executable</span>(Tutorial tutorial.cxx)</span><br><span class="line"></span><br><span class="line"><span class="keyword">target_link_libraries</span>(Tutorial PUBLIC MathFunctions)</span><br><span class="line"></span><br><span class="line"><span class="comment"># add the binary tree to the search path for include files</span></span><br><span class="line"><span class="comment"># so that we will find TutorialConfig.h</span></span><br><span class="line"><span class="keyword">target_include_directories</span>(Tutorial PUBLIC</span><br><span class="line">                          <span class="string">"$&#123;PROJECT_BINARY_DIR&#125;"</span></span><br><span class="line">                          <span class="string">"$&#123;PROJECT_SOURCE_DIR&#125;/MathFunctions"</span></span><br><span class="line">                          )</span><br></pre></td></tr></table></figure>

<p>接下来，让我们将<code>MathFunctions</code>设为可选库。虽然对于本教程来说，没有必要这样做，但是对于较大的项目来说，这是很常见的。第一步是向顶层<code>CMakeLists.txt</code>添加一个选项。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">option(USE_MYMATH &quot;Use tutorial provided math implementation&quot; ON)</span><br><span class="line"></span><br><span class="line"># configure a header file to pass some of the CMake settings</span><br><span class="line"># to the source code</span><br><span class="line">configure_file(TutorialConfig.h.in TutorialConfig.h)</span><br></pre></td></tr></table></figure>

<p>此选项将显示在<code>cmake-gui</code>和<code>ccmake</code>中，默认值为ON，用户可以更改该值。此选项值保存在缓存中，这样用户不需要在每次CMake该工程时都设置此选项。</p>
<p>下一处修改是让构建和链接MathFunctions库变为可选的。为此，我们将顶层<code>CMakeLists.txt</code>的末尾更改如下:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span>(USE_MYMATH)</span><br><span class="line">  <span class="keyword">add_subdirectory</span>(MathFunctions)</span><br><span class="line">  <span class="keyword">list</span>(APPEND EXTRA_LIBS MathFunctions)</span><br><span class="line">  <span class="keyword">list</span>(APPEND EXTRA_INCLUDES <span class="string">"$&#123;PROJECT_SOURCE_DIR&#125;/MathFunctions"</span>)</span><br><span class="line"><span class="keyword">endif</span>()</span><br><span class="line"></span><br><span class="line"><span class="comment"># add the executable</span></span><br><span class="line"><span class="keyword">add_executable</span>(Tutorial tutorial.cxx)</span><br><span class="line"></span><br><span class="line"><span class="keyword">target_link_libraries</span>(Tutorial PUBLIC <span class="variable">$&#123;EXTRA_LIBS&#125;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># add the binary tree to the search path for include files</span></span><br><span class="line"><span class="comment"># so that we will find TutorialConfig.h</span></span><br><span class="line"><span class="keyword">target_include_directories</span>(Tutorial PUBLIC</span><br><span class="line">                           <span class="string">"$&#123;PROJECT_BINARY_DIR&#125;"</span></span><br><span class="line">                           <span class="variable">$&#123;EXTRA_INCLUDES&#125;</span></span><br><span class="line">                           )</span><br></pre></td></tr></table></figure>

<p>注意，使用变量<code>EXTRA_LIBS</code>来保存所有以后会被链接进可执行文件中的可选库，变量<code>EXTRA_INCLUDES</code>类似地用来保存可选的头文件搜索路径。这是处理许多可选组件时的经典方法，我们将在下一步介绍更新的方法。</p>
<p>相应的，对源代码进行简单更改。首先，在<code>tutorial.cxx</code>中，按需包含<code>MathFunctions.h</code>头:</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> USE_MYMATH</span></span><br><span class="line"><span class="meta">#  <span class="meta-keyword">include</span> <span class="meta-string">"MathFunctions.h"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br></pre></td></tr></table></figure>

<p>然后，在同一个文件中，使用<code>USE_MYMATH</code>来控制调用哪个平方根函数:</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> USE_MYMATH</span></span><br><span class="line">  <span class="keyword">const</span> <span class="keyword">double</span> outputValue = mysqrt(inputValue);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">else</span></span></span><br><span class="line">  <span class="keyword">const</span> <span class="keyword">double</span> outputValue = <span class="built_in">sqrt</span>(inputValue);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br></pre></td></tr></table></figure>

<p>由于源代码现在需要<code>USE_MYMATH</code>，我们可以将下列内容添加到<code>TutorialConfig.h.in</code>中:</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#cmakedefine USE_MYMATH</span></span><br></pre></td></tr></table></figure>

<p>练习: 为什么在<code>USE_MYMATH</code>选项之后, 配置<code>TutorialConfig.h.in</code>很重要? 如果我们把这两者颠倒过来会发生什么?</p>
<p>运行<code>cmake</code>可执行文件或<code>cmake-gui</code>来配置项目，然后使用您选择的构建工具来构建它。然后运行构建的<code>Tutorial</code>可执行文件（参见第一步）。</p>
<p>使用<code>ccmake</code>可执行文件或<code>cmake-gui</code>来更新<code>USE_MYMATH</code>的值。重新构建并再次运行教程。哪个函数的结果更好，sqrt还是mysqrt?</p>
<h2 id="第3步-为库添加使用要求-Adding-Usage-Requirements-for-Library-Step-3"><a href="#第3步-为库添加使用要求-Adding-Usage-Requirements-for-Library-Step-3" class="headerlink" title="第3步 为库添加使用要求 Adding Usage Requirements for Library (Step 3)"></a>第3步 为库添加使用要求 Adding Usage Requirements for Library (Step 3)</h2><p>使用要求对库或可执行文件的链接和包含(link and include)提供了更好的控制，也对CMake内传递目标属性更加可控。影响使用要求的主要命令有:</p>
<ul>
<li>target_compile_definitions ()</li>
<li>target_compile_options ()</li>
<li>target_include_directories ()</li>
<li>target_link_libraries ()</li>
</ul>
<p>让我们用新式CMake中的<strong>使用要求</strong>来重构《添加库》(第二步)。首先要说明一下，任何链接到<code>MathFunctions</code>的人都需要包含<code>MathFunctions</code>源目录，但<code>MathFunctions</code>库本身不需要。所以这个可以变成<code>INTERFACE</code>使用要求。</p>
<p>记住，<code>INTERFACE</code>是指消费者需要但生产者不需要的东西。在<code>MathFunctions/CMakeLists.txt</code>末尾添加以下代码:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">target_include_directories</span>(MathFunctions</span><br><span class="line">  INTERFACE <span class="variable">$&#123;CMAKE_CURRENT_SOURCE_DIR&#125;</span></span><br><span class="line">  )</span><br></pre></td></tr></table></figure>

<p>至此，我们已经为<code>MathFunctions</code>库指定了使用要求，我们可以安全地从顶层<code>CMakeLists.txt</code>中如下位置删除<code>EXTRA_INCLUDES</code>变量:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span>(USE_MYMATH)</span><br><span class="line">  <span class="keyword">add_subdirectory</span>(MathFunctions)</span><br><span class="line">  <span class="keyword">list</span>(APPEND EXTRA_LIBS MathFunctions)</span><br><span class="line"><span class="keyword">endif</span>()</span><br></pre></td></tr></table></figure>

<p>还有这里:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">target_include_directories</span>(Tutorial PUBLIC</span><br><span class="line">                           <span class="string">"$&#123;PROJECT_BINARY_DIR&#125;"</span></span><br><span class="line">                           )</span><br></pre></td></tr></table></figure>

<p>做完这些，运行<code>cmake</code>可执行文件或<code>cmake-gui</code>来配置项目，然后使用您选择的构建工具来构建它或在构建目录下使用<code>cmake --build .</code>。</p>
<h2 id="第4步-安装和测试-Installing-and-Testing-Step-4"><a href="#第4步-安装和测试-Installing-and-Testing-Step-4" class="headerlink" title="第4步 安装和测试 Installing and Testing (Step 4)"></a>第4步 安装和测试 Installing and Testing (Step 4)</h2><p>现在，我们将开始向项目添加安装规则和测试支持。</p>
<h3 id="4-1-安装规则"><a href="#4-1-安装规则" class="headerlink" title="4.1 安装规则"></a>4.1 安装规则</h3><p>安装规则相当简单: 对于<code>MathFunctions</code>，我们希望安装库和头文件; 对于应用程序，我们希望安装可执行文件和配置的头文件。</p>
<p>因此，在<code>MathFunctions/CMakeLists.txt</code>的末尾添加:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">install</span>(TARGETS MathFunctions DESTINATION lib)</span><br><span class="line"><span class="keyword">install</span>(FILES MathFunctions.h DESTINATION <span class="keyword">include</span>)</span><br></pre></td></tr></table></figure>

<p>在顶层<code>CMakeLists.txt</code>末尾添加:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">install</span>(TARGETS Tutorial DESTINATION bin)</span><br><span class="line"><span class="keyword">install</span>(FILES <span class="string">"$&#123;PROJECT_BINARY_DIR&#125;/TutorialConfig.h"</span></span><br><span class="line">  DESTINATION <span class="keyword">include</span></span><br><span class="line">  )</span><br></pre></td></tr></table></figure>

<p>这就是创建基本的<code>tutorial</code>本地安装需要做的全部工作。</p>
<p>运行<code>cmake</code>可执行文件或<code>cmake-gui</code>来配置项目，然后使用您选择的构建工具来构建它。在命令行中使用<code>cmake</code>命令的<code>install</code>选项(在3.15中引入，较老的cmake版本必须使用<code>make install</code>)来运行安装步骤，或者从IDE构建<code>INSTALL</code>目标。这将安装相应的头文件、库和可执行文件。</p>
<p>CMake变量<code>CMAKE_INSTALL_PREFIX</code>用于确定文件安装的根目录。如果使用<code>cmake --install</code>，可以通过<code>--prefix</code>参数提供自定义安装目录。对于多配置工具(Release;Debug)，使用<code>--config</code>参数来指定配置。</p>
<p>验证安装的<code>Tutorial</code>程序是否运行。</p>
<p><code>win10</code>各参数命令行示例如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">PS &gt; cmake --install . --prefix D:\Temp2\ttt\debug --config debug</span><br><span class="line">根据cmake_install.cmake文件及目录下项目文件安装</span><br></pre></td></tr></table></figure>

<h3 id="4-2-测试支持-Testing-Support"><a href="#4-2-测试支持-Testing-Support" class="headerlink" title="4.2 测试支持 Testing Support"></a>4.2 测试支持 Testing Support</h3><p>接下来，让我们测试应用程序。在顶层<code>CMakeLists.txt</code>的末尾，我们可以启用测试，然后添加一些基本测试来验证应用程序是否工作正确。</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">enable_testing</span>()</span><br><span class="line"></span><br><span class="line"><span class="comment"># does the application run</span></span><br><span class="line"><span class="keyword">add_test</span>(NAME Runs <span class="keyword">COMMAND</span> Tutorial <span class="number">25</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># does the usage message work?</span></span><br><span class="line"><span class="keyword">add_test</span>(NAME Usage <span class="keyword">COMMAND</span> Tutorial)</span><br><span class="line"><span class="keyword">set_tests_properties</span>(Usage</span><br><span class="line">  PROPERTIES PASS_REGULAR_EXPRESSION <span class="string">"Usage:.*number"</span></span><br><span class="line">  )</span><br><span class="line"></span><br><span class="line"><span class="comment"># define a function to simplify adding tests</span></span><br><span class="line"><span class="keyword">function</span>(do_test <span class="keyword">target</span> arg result)</span><br><span class="line">  <span class="keyword">add_test</span>(NAME Comp<span class="variable">$&#123;arg&#125;</span> <span class="keyword">COMMAND</span> <span class="variable">$&#123;target&#125;</span> <span class="variable">$&#123;arg&#125;</span>)</span><br><span class="line">  <span class="keyword">set_tests_properties</span>(Comp<span class="variable">$&#123;arg&#125;</span></span><br><span class="line">    PROPERTIES PASS_REGULAR_EXPRESSION <span class="variable">$&#123;result&#125;</span></span><br><span class="line">    )</span><br><span class="line"><span class="keyword">endfunction</span>(do_test)</span><br><span class="line"></span><br><span class="line"><span class="comment"># do a bunch of result based tests</span></span><br><span class="line">do_test(Tutorial <span class="number">4</span> <span class="string">"4 is 2"</span>)</span><br><span class="line">do_test(Tutorial <span class="number">9</span> <span class="string">"9 is 3"</span>)</span><br><span class="line">do_test(Tutorial <span class="number">5</span> <span class="string">"5 is 2.236"</span>)</span><br><span class="line">do_test(Tutorial <span class="number">7</span> <span class="string">"7 is 2.645"</span>)</span><br><span class="line">do_test(Tutorial <span class="number">25</span> <span class="string">"25 is 5"</span>)</span><br><span class="line">do_test(Tutorial -<span class="number">25</span> <span class="string">"-25 is [-nan|nan|0]"</span>)</span><br><span class="line">do_test(Tutorial <span class="number">0.0001</span> <span class="string">"0.0001 is 0.01"</span>)</span><br></pre></td></tr></table></figure>

<p>第一个测试只是验证应用程序能够运行，不会发生断错误(segfault)或其他崩溃，并且返回0。这是CTest中<code>test</code>的基本形式。</p>
<p>下一个测试使用<code>PASS_REGULAR_EXPRESSION</code>测试属性来验证测试的输出是否包含某些字符串。在本例中，验证当输入错误的参数数量时应用程序能够输出使用说明。</p>
<p>最后，我们定义一个名为<code>do_test</code>的函数，该函数运行应用程序并且验证输出的平方根与给定的结果相同。每次<code>do_test</code>调用，该函数都会基于调用参数向项目添加一个带名称、输入和预期结果的测试。</p>
<p>重新构建应用程序，然后将<code>切换(cd)</code>到执行文件目录中，并运行ctest可执行文件:<code>ctest -N</code>和<code>ctest -VV</code>。</p>
<p>对于多配置生成器(例如Visual Studio)，必须指定配置类型。例如，要在调试模式下运行测试，请在构建目录(不是调试子目录!)下执行<code>ctest -C Debug -VV</code>。或者，在IDE中构建<code>RUN_TESTS</code>目标。</p>
<h2 id="第5步-添加系统自检-Adding-System-Introspection-Step-5"><a href="#第5步-添加系统自检-Adding-System-Introspection-Step-5" class="headerlink" title="第5步 添加系统自检 Adding System Introspection (Step 5)"></a>第5步 添加系统自检 Adding System Introspection (Step 5)</h2><p>让我们在源码中添加一些目标平台可能不支持的特性。对于本例，我们将添加一些代码，同时会根据目标平台是否支持<code>log</code>和<code>exp</code>函数来选择是否包含这些代码。当然，几乎每个平台都有这些函数，但是本教程假设它们并不常见。</p>
<p>如果平台支持<code>log</code>和<code>exp</code>函数，那么我们将在<code>mysqrt</code>函数中使用它们来计算平方根。我们首先在顶层<code>CMakeLists.txt</code>中使用<code>CheckSymbolExists</code>模块来检查这些函数的可用性。因为我们将在<code>TutorialConfig.h.in</code>中使用新定义，因此，一定要在文件配置之前设置它们。</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">include</span>(CheckSymbolExists)</span><br><span class="line"><span class="keyword">set</span>(CMAKE_REQUIRED_LIBRARIES <span class="string">"m"</span>)</span><br><span class="line">check_symbol_exists(log <span class="string">"math.h"</span> HAVE_LOG)</span><br><span class="line">check_symbol_exists(exp <span class="string">"math.h"</span> HAVE_EXP)</span><br></pre></td></tr></table></figure>

<p>现在让我们将这些定义添加到<code>TutorialConfig.h.in</code>中，这样我们就可以从<code>mysqrt.cxx</code>中使用它们:</p>
<figure class="highlight h"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// does the platform provide exp and log functions?</span></span><br><span class="line"><span class="meta">#cmakedefine HAVE_LOG</span></span><br><span class="line"><span class="meta">#cmakedefine HAVE_EXP</span></span><br></pre></td></tr></table></figure>

<p>如果系统支持<code>log</code>和<code>exp</code>函数，那么我们将使用它们来计算<code>mysqrt</code>函数中的平方根。将以下代码添加到<code>MathFunctions/mysqrt.cxx</code>中的<code>mysqrt</code>函数(在返回结果之前不要忘记<code>#endif</code>!):</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">if</span> defined(HAVE_LOG) &amp;&amp; defined(HAVE_EXP)</span></span><br><span class="line">  <span class="keyword">double</span> result = <span class="built_in">exp</span>(<span class="built_in">log</span>(x) * <span class="number">0.5</span>);</span><br><span class="line">  <span class="built_in">std</span>::<span class="built_in">cout</span> &lt;&lt; <span class="string">"Computing sqrt of "</span> &lt;&lt; x &lt;&lt; <span class="string">" to be "</span> &lt;&lt; result</span><br><span class="line">            &lt;&lt; <span class="string">" using log and exp"</span> &lt;&lt; <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">else</span></span></span><br><span class="line">  <span class="keyword">double</span> result = x;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br></pre></td></tr></table></figure>

<p>我们还需要修改<code>mysqrt.cxx</code>以包含<code>cmath</code>.</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cmath&gt;</span></span></span><br></pre></td></tr></table></figure>

<p>运行<code>cmake</code>可执行文件或<code>cmake-gui</code>来配置项目，然后使用您选择的构建工具构建它，并运行<code>Tutorial</code>可执行文件。</p>
<p>您将注意到，我们没有使用<code>log</code>和<code>exp</code>，即使我们认为它们应该可用。我们应该很快意识到，我们忘了在<code>mysqrt.cxx</code>中包含<code>TutorialConfig.h</code>。</p>
<p>我们还需要更新<code>MathFunctions/CMakeLists.txt</code>，以便让<code>mysqrt.cxx</code>知道这个文件的位置:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">target_include_directories</span>(MathFunctions</span><br><span class="line">          INTERFACE <span class="variable">$&#123;CMAKE_CURRENT_SOURCE_DIR&#125;</span></span><br><span class="line">          PRIVATE <span class="variable">$&#123;CMAKE_BINARY_DIR&#125;</span></span><br><span class="line">          )</span><br></pre></td></tr></table></figure>

<p>进行此更新后，继续重新构建项目并运行构建的教程可执行文件。如果仍然没有使用<code>log</code>和<code>exp</code>，那么在构建目录中查看生成的<code>TutorialConfig.h</code>文件，也许它们在当前的系统中不可用?</p>
<p>现在哪个函数的结果更好，sqrt还是mysqrt?</p>
<h3 id="指定编译时宏定义-Specify-Compile-Definition"><a href="#指定编译时宏定义-Specify-Compile-Definition" class="headerlink" title="指定编译时宏定义 Specify Compile Definition"></a>指定编译时宏定义 Specify Compile Definition</h3><p>除了在<code>TutorialConfig.h</code>中保存<code>HAVE_LOG</code>和<code>HAVE_EXP</code>值，还有更好的地方吗? 让我们尝试使用<code>target_compile_definitions()</code>。</p>
<p>首先，从<code>TutorialConfig.h.in</code>中删除这些定义。我们不再需要在<code>mysqrt.cxx</code>中包含<code>TutorialConfig.h</code>以及在<code>MathFunctions/CMakeLists.txt</code>中包含额外的头文件路径。</p>
<p>接下来，我们可以将<code>HAVE_LOG</code>和<code>HAVE_EXP</code>的检查移到<code>MathFunctions/CMakeLists.txt</code>中，然后将这些值指定为<code>PRIVATE</code>编译时宏定义。</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">include</span>(CheckSymbolExists)</span><br><span class="line"><span class="keyword">set</span>(CMAKE_REQUIRED_LIBRARIES <span class="string">"m"</span>)</span><br><span class="line">check_symbol_exists(log <span class="string">"math.h"</span> HAVE_LOG)</span><br><span class="line">check_symbol_exists(exp <span class="string">"math.h"</span> HAVE_EXP)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span>(HAVE_LOG <span class="keyword">AND</span> HAVE_EXP)</span><br><span class="line">  <span class="keyword">target_compile_definitions</span>(MathFunctions</span><br><span class="line">                             PRIVATE <span class="string">"HAVE_LOG"</span> <span class="string">"HAVE_EXP"</span>)</span><br><span class="line"><span class="keyword">endif</span>()</span><br></pre></td></tr></table></figure>

<p>完成这些更新之后，重新构建项目。运行构建的Tutorial可执行文件，并验证结果是否与本步骤前面的结果相同。</p>
<h2 id="第6步-添加自定义命令以及生成文件-Adding-a-Custom-Command-and-Generated-File-Step-6"><a href="#第6步-添加自定义命令以及生成文件-Adding-a-Custom-Command-and-Generated-File-Step-6" class="headerlink" title="第6步 添加自定义命令以及生成文件 Adding a Custom Command and Generated File (Step 6)"></a>第6步 添加自定义命令以及生成文件 Adding a Custom Command and Generated File (Step 6)</h2><p>假设，出于本教程的目的，我们决定不使用平台<code>log</code>和<code>exp</code>函数，而是希望生成一个可在<code>mysqrt</code>函数中使用的预计算值表。在本节中，我们将在构建过程中创建该表，然后将该表编译到我们的应用程序中。</p>
<p>首先，让我们删除<code>MathFunctions/CMakeLists.txt</code>中对<code>log</code>和<code>exp</code>函数的检查。然后从<code>mysqrt.cxx</code>中删除对<code>HAVE_LOG</code>和<code>HAVE_EXP</code>的检查。同时，我们可以删除<code>#include &lt;cmath&gt;</code>。</p>
<p>在<code>MathFunctions</code>子目录中，提供了一个用来生成该表的源码文件<code>MakeTable.cxx</code>。</p>
<p>通过分析该源代码可以看到，它以传入参数作为输出文件名，生成包含预计算值表的一段C++代码。</p>
<p>下一步，让我们在<code>MathFunctions/CMakeLists.txt</code>中添加合适的命令来编译<code>MakeTable</code>，并在构建项目的过程中运行这个可执行文件。为此，需要一些命令来完成这项工作。</p>
<p>首先，在<code>MathFunctions/CMakeLists.txt</code>头部, 添加<code>MakeTable</code>可执行文件，就像添加任何其他可执行文件一样。</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">add_executable</span>(MakeTable MakeTable.cxx)</span><br></pre></td></tr></table></figure>

<p>然后，我们添加一个自定义命令，该命令指定如何运行<code>MakeTable</code>来生成<code>Table.h</code>。</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">add_custom_command</span>(</span><br><span class="line">  OUTPUT <span class="variable">$&#123;CMAKE_CURRENT_BINARY_DIR&#125;</span>/Table.h</span><br><span class="line">  <span class="keyword">COMMAND</span> MakeTable <span class="variable">$&#123;CMAKE_CURRENT_BINARY_DIR&#125;</span>/Table.h</span><br><span class="line">  DEPENDS MakeTable</span><br><span class="line">  )</span><br></pre></td></tr></table></figure>

<p>接下来，我们需要让CMake知道<code>mysqrt.cxx</code>依赖于生成的<code>Table.h</code>。通过在<code>MathFunctions</code>的源文件列表中添加<code>Table.h</code>来实现。</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">add_library</span>(MathFunctions</span><br><span class="line">            mysqrt.cxx</span><br><span class="line">            <span class="variable">$&#123;CMAKE_CURRENT_BINARY_DIR&#125;</span>/Table.h</span><br><span class="line">            )</span><br></pre></td></tr></table></figure>

<p>我们还必须将当前的二进制目录添加到头文件包含路径中，以便<code>mysqrt.cxx</code>能够找到并包含<code>Table.h</code>。</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">target_include_directories</span>(MathFunctions</span><br><span class="line">          INTERFACE <span class="variable">$&#123;CMAKE_CURRENT_SOURCE_DIR&#125;</span></span><br><span class="line">          PRIVATE <span class="variable">$&#123;CMAKE_CURRENT_BINARY_DIR&#125;</span></span><br><span class="line">          )</span><br></pre></td></tr></table></figure>

<p>现在，让我们使用生成的表。首先，修改<code>mysqrt.cxx</code>以包含<code>Table.h</code>。接下来，我们可以重写<code>mysqrt</code>函数来使用该表:</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">double</span> <span class="title">mysqrt</span><span class="params">(<span class="keyword">double</span> x)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="keyword">if</span> (x &lt;= <span class="number">0</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// use the table to help find an initial value</span></span><br><span class="line">  <span class="keyword">double</span> result = x;</span><br><span class="line">  <span class="keyword">if</span> (x &gt;= <span class="number">1</span> &amp;&amp; x &lt; <span class="number">10</span>) &#123;</span><br><span class="line">    <span class="built_in">std</span>::<span class="built_in">cout</span> &lt;&lt; <span class="string">"Use the table to help find an initial value "</span> &lt;&lt; <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">    result = sqrtTable[<span class="keyword">static_cast</span>&lt;<span class="keyword">int</span>&gt;(x)];</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// do ten iterations</span></span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">10</span>; ++i) &#123;</span><br><span class="line">    <span class="keyword">if</span> (result &lt;= <span class="number">0</span>) &#123;</span><br><span class="line">      result = <span class="number">0.1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">double</span> delta = x - (result * result);</span><br><span class="line">    result = result + <span class="number">0.5</span> * delta / result;</span><br><span class="line">    <span class="built_in">std</span>::<span class="built_in">cout</span> &lt;&lt; <span class="string">"Computing sqrt of "</span> &lt;&lt; x &lt;&lt; <span class="string">" to be "</span> &lt;&lt; result &lt;&lt; <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>运行<code>cmake</code>可执行文件或<code>cmake-gui</code>来配置项目，然后使用您选择的构建工具来构建它。</p>
<p>当构建该项目时，它将首先构建<code>MakeTable</code>可执行文件；然后运行<code>MakeTable</code>来生成<code>Table.h</code>；最后，它将编译<code>mysqrt.cxx</code>，其中包含<code>Table.h</code>来生成<code>MathFunctions</code>库。</p>
<p>运行该<code>Tutorial</code>的可执行文件，并验证它正在使用该表。</p>
<h2 id="第7步-构建安装程序-Building-an-Installer-Step-7"><a href="#第7步-构建安装程序-Building-an-Installer-Step-7" class="headerlink" title="第7步 构建安装程序 Building an Installer (Step 7)"></a>第7步 构建安装程序 Building an Installer (Step 7)</h2><p>接下来，假设我们想要将我们的项目分发给其他人，这样他们可以使用它。我们希望在各种平台上提供二进制和源代码发行版。这与我们之前在安装和测试(步骤4)中安装的稍有不同，我们在其中安装了从源代码构建的二进制文件。在本例中，我们将构建支持二进制安装和包管理特性的安装包。为了实现这一点，我们将使用CPack来创建特定于平台的安装程序。具体来说，我们需要在顶层<code>CMakeLists.txt</code>的结尾增加以下内容。</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">include</span>(InstallRequiredSystemLibraries)</span><br><span class="line"><span class="keyword">set</span>(CPACK_RESOURCE_FILE_LICENSE <span class="string">"$&#123;CMAKE_CURRENT_SOURCE_DIR&#125;/License.txt"</span>)</span><br><span class="line"><span class="keyword">set</span>(CPACK_PACKAGE_VERSION_MAJOR <span class="string">"$&#123;Tutorial_VERSION_MAJOR&#125;"</span>)</span><br><span class="line"><span class="keyword">set</span>(CPACK_PACKAGE_VERSION_MINOR <span class="string">"$&#123;Tutorial_VERSION_MINOR&#125;"</span>)</span><br><span class="line"><span class="keyword">include</span>(CPack)</span><br></pre></td></tr></table></figure>

<p>这就是它的全部。我们首先包含<code>InstallRequiredSystemLibraries</code>。此模块将包含项目当前平台所需的任何运行时库。接下来，是一些CPack变量, 用于设置该项目许可文件和版本信息。版本信息是在本教程前面设置的，此步骤的顶层源目录中包含了<code>license.txt</code>。</p>
<p>最后，我们包括了<code>CPack模块</code>，它将使用这些变量和当前系统的一些其他属性来设置安装程序。</p>
<p>下一步是按照通常的方式构建项目，然后运行<code>cpack</code>可执行文件。要构建一个二进制发行版，从二进制目录运行:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cpack</span><br></pre></td></tr></table></figure>

<p>要指定生成器，请使用-G选项。对于多配置构建，使用-C来指定配置。例如:<br>To specify the generator, use the -G option. For multi-config builds, use -C to specify the configuration.</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cpack -G ZIP -C Debug</span><br></pre></td></tr></table></figure>

<p>要创建一个源发行版，你需要输入:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cpack --config CPackSourceConfig.cmake</span><br></pre></td></tr></table></figure>

<p>或者，运行<code>make package</code>或右键单击<code>Package</code>目标并从IDE构建项目。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">VS generator 注意：目录不能含有中文</span><br><span class="line">$ cmake --build . --target PACKAGE --config Release[Debug]</span><br></pre></td></tr></table></figure>

<p>运行在二进制目录中找到的安装程序。然后运行已安装的可执行文件并验证它是否工作。</p>
<h4 id="注-目标包和package-source"><a href="#注-目标包和package-source" class="headerlink" title="注: 目标包和package_source"></a>注: 目标包和package_source</h4><ol>
<li>如果CMake是用Makefile、Ninja或Xcode生成器运行的，那么<code>include(CPack)</code>将生成一个目标<code>package</code>，这样，可以通过CMake、Make或Ninja命令来构建二进制安装程序（<code>cmake --build . --target package or make package or ninja package</code>）来代替cpack。</li>
<li>VS生成器创建一个大写目标<code>PACKAGE</code>。</li>
<li>如果CMake是用Makefile或Ninja生成器运行的，那么<code>include(CPack)</code>还会生成一个目标<code>package_source</code>。要构建一个源包，可以调用<code>cmake --build . --target package_source, make package_source, or ninja package_source.</code>来替代<code>cpack -G TGZ --config CPackConfig.cmake</code>。</li>
</ol>
<h2 id="第8步-添加对仪表板的支持-Adding-Support-for-a-Dashboard-Step-8"><a href="#第8步-添加对仪表板的支持-Adding-Support-for-a-Dashboard-Step-8" class="headerlink" title="第8步 添加对仪表板的支持 Adding Support for a Dashboard (Step 8)"></a>第8步 添加对仪表板的支持 Adding Support for a Dashboard (Step 8)</h2><p>添加向仪表板提交测试结果的支持也很简单。我们已经在<code>测试支持(第四步)</code>一节中为项目定义了一些测试。现在我们只需要运行这些测试并将它们提交到仪表板。为了包含对仪表板的支持，我们在顶层<code>CMakeLists.txt</code>中包含<code>CTest</code>模块。</p>
<p>将:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># enable testing</span></span><br><span class="line"><span class="keyword">enable_testing</span>()</span><br></pre></td></tr></table></figure>

<p>替换为:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># enable dashboard scripting</span></span><br><span class="line"><span class="keyword">include</span>(CTest)</span><br></pre></td></tr></table></figure>

<p><code>CTest</code>模块将自动调用<code>enable_testing()</code>，因此我们可以从CMake文件中删除它。</p>
<p>我们还需要在顶级目录中创建一个<code>CTestConfig.cmake</code>文件，我们可以在其中指定项目的名称和提交仪表板的位置。</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">set</span>(CTEST_PROJECT_NAME <span class="string">"CMakeTutorial"</span>)</span><br><span class="line"><span class="keyword">set</span>(CTEST_NIGHTLY_START_TIME <span class="string">"00:00:00 EST"</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">set</span>(CTEST_DROP_METHOD <span class="string">"http"</span>)</span><br><span class="line"><span class="keyword">set</span>(CTEST_DROP_SITE <span class="string">"my.cdash.org"</span>)</span><br><span class="line"><span class="keyword">set</span>(CTEST_DROP_LOCATION <span class="string">"/submit.php?project=CMakeTutorial"</span>)</span><br><span class="line"><span class="keyword">set</span>(CTEST_DROP_SITE_CDASH <span class="keyword">TRUE</span>)</span><br></pre></td></tr></table></figure>

<p><code>ctest</code>可执行文件在运行时将读取这个文件。要创建一个简单的指示板，您可以运行<code>cmake</code>可执行文件或<code>cmake-gui</code>来配置项目，但不要构建它。相反，切换到二进制目录，然后运行:<br><code>ctest [-VV] -D Experimental</code></p>
<p>请记住，对于多配置生成器(例如Visual Studio)，必须指定配置类型:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ctest [-VV] -C Debug -D Experimental</span><br></pre></td></tr></table></figure>

<p>或者，从IDE构建<code>Experimental</code>目标。<br><code>ctest</code>可执行文件将构建并测试项目，并将结果提交到Kitware的公共指示板:<code>https://my.cdash.org/index.php?project=CMakeTutorial</code>.</p>
<h2 id="第9步-混合静态和共享库-Mixing-Static-and-Shared-Step-9"><a href="#第9步-混合静态和共享库-Mixing-Static-and-Shared-Step-9" class="headerlink" title="第9步 混合静态和共享库 Mixing Static and Shared (Step 9)"></a>第9步 混合静态和共享库 Mixing Static and Shared (Step 9)</h2><p>在本节中，我们将展示如何使用<code>BUILD_SHARED_LIBS</code>变量来控制<code>add_library()</code>的默认行为，并允许在没有显式类型(<code>STATIC</code>, <code>SHARED</code>, <code>MODULE</code> 或 <code>OBJECT</code>)的情况下控制如何构建库。</p>
<p>为此，我们需要将<code>BUILD_SHARED_LIBS</code>添加到顶层<code>CMakeLists.txt</code>中。我们使用<code>option()</code>命令，它允许用户在<code>ON</code>或<code>OFF</code>值中选择。</p>
<p>接下来，我们将把<code>MathFunctions</code>重构为一个真正的库，它使用<code>mysqrt</code>或<code>sqrt</code>进行封装，而不需要调用代码来执行此逻辑。这也意味着<code>USE_MYMATH</code>将不控制构建<code>mathfunction</code>，而是控制库的行为。</p>
<p>第一步是将顶层<code>CMakeLists.txt</code>的起始部分更新为:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">cmake_minimum_required</span>(VERSION <span class="number">3.10</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># set the project name and version</span></span><br><span class="line"><span class="keyword">project</span>(Tutorial VERSION <span class="number">1.0</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># specify the C++ standard</span></span><br><span class="line"><span class="keyword">set</span>(CMAKE_CXX_STANDARD <span class="number">11</span>)</span><br><span class="line"><span class="keyword">set</span>(CMAKE_CXX_STANDARD_REQUIRED <span class="keyword">True</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># control where the static and shared libraries are built so that on windows</span></span><br><span class="line"><span class="comment"># we don't need to tinker with the path to run the executable</span></span><br><span class="line"><span class="keyword">set</span>(CMAKE_ARCHIVE_OUTPUT_DIRECTORY <span class="string">"$&#123;PROJECT_BINARY_DIR&#125;"</span>)</span><br><span class="line"><span class="keyword">set</span>(CMAKE_LIBRARY_OUTPUT_DIRECTORY <span class="string">"$&#123;PROJECT_BINARY_DIR&#125;"</span>)</span><br><span class="line"><span class="keyword">set</span>(CMAKE_RUNTIME_OUTPUT_DIRECTORY <span class="string">"$&#123;PROJECT_BINARY_DIR&#125;"</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">option</span>(BUILD_SHARED_LIBS <span class="string">"Build using shared libraries"</span> <span class="keyword">ON</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># configure a header file to pass the version number only</span></span><br><span class="line"><span class="keyword">configure_file</span>(TutorialConfig.h.in TutorialConfig.h)</span><br><span class="line"></span><br><span class="line"><span class="comment"># add the MathFunctions library</span></span><br><span class="line"><span class="keyword">add_subdirectory</span>(MathFunctions)</span><br><span class="line"></span><br><span class="line"><span class="comment"># add the executable</span></span><br><span class="line"><span class="keyword">add_executable</span>(Tutorial tutorial.cxx)</span><br><span class="line"><span class="keyword">target_link_libraries</span>(Tutorial PUBLIC MathFunctions)</span><br></pre></td></tr></table></figure>

<p>现在我们已经使用<code>MathFunctions</code>库，我们将需要更新该库的逻辑。因此，在<code>MathFunctions/CMakeLists.txt</code>中，我们需要创建一个SqrtLibrary，它将在启用<code>USE_MYMATH</code>时有条件地构建。现在，出于教程的目标，我们将明确要求SqrtLibrary是静态构建的。</p>
<p><code>MathFunctions/CMakeLists.txt</code>最终的结果应该如下:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># add the library that runs</span></span><br><span class="line"><span class="keyword">add_library</span>(MathFunctions MathFunctions.cxx)</span><br><span class="line"></span><br><span class="line"><span class="comment"># state that anybody linking to us needs to include the current source dir</span></span><br><span class="line"><span class="comment"># to find MathFunctions.h, while we don't.</span></span><br><span class="line"><span class="keyword">target_include_directories</span>(MathFunctions</span><br><span class="line">                           INTERFACE <span class="variable">$&#123;CMAKE_CURRENT_SOURCE_DIR&#125;</span></span><br><span class="line">                           )</span><br><span class="line"></span><br><span class="line"><span class="comment"># should we use our own math functions</span></span><br><span class="line"><span class="keyword">option</span>(USE_MYMATH <span class="string">"Use tutorial provided math implementation"</span> <span class="keyword">ON</span>)</span><br><span class="line"><span class="keyword">if</span>(USE_MYMATH)</span><br><span class="line"></span><br><span class="line">  <span class="keyword">target_compile_definitions</span>(MathFunctions PRIVATE <span class="string">"USE_MYMATH"</span>)</span><br><span class="line"></span><br><span class="line">  <span class="comment"># first we add the executable that generates the table</span></span><br><span class="line">  <span class="keyword">add_executable</span>(MakeTable MakeTable.cxx)</span><br><span class="line"></span><br><span class="line">  <span class="comment"># add the command to generate the source code</span></span><br><span class="line">  <span class="keyword">add_custom_command</span>(</span><br><span class="line">    OUTPUT <span class="variable">$&#123;CMAKE_CURRENT_BINARY_DIR&#125;</span>/Table.h</span><br><span class="line">    <span class="keyword">COMMAND</span> MakeTable <span class="variable">$&#123;CMAKE_CURRENT_BINARY_DIR&#125;</span>/Table.h</span><br><span class="line">    DEPENDS MakeTable</span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line">  <span class="comment"># library that just does sqrt</span></span><br><span class="line">  <span class="keyword">add_library</span>(SqrtLibrary STATIC</span><br><span class="line">              mysqrt.cxx</span><br><span class="line">              <span class="variable">$&#123;CMAKE_CURRENT_BINARY_DIR&#125;</span>/Table.h</span><br><span class="line">              )</span><br><span class="line"></span><br><span class="line">  <span class="comment"># state that we depend on our binary dir to find Table.h</span></span><br><span class="line">  <span class="keyword">target_include_directories</span>(SqrtLibrary PRIVATE</span><br><span class="line">                             <span class="variable">$&#123;CMAKE_CURRENT_BINARY_DIR&#125;</span></span><br><span class="line">                             )</span><br><span class="line"></span><br><span class="line">  <span class="keyword">target_link_libraries</span>(MathFunctions PRIVATE SqrtLibrary)</span><br><span class="line"><span class="keyword">endif</span>()</span><br><span class="line"></span><br><span class="line"><span class="comment"># define the symbol stating we are using the declspec(dllexport) when</span></span><br><span class="line"><span class="comment"># building on windows</span></span><br><span class="line"><span class="keyword">target_compile_definitions</span>(MathFunctions PRIVATE <span class="string">"EXPORTING_MYMATH"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># install rules</span></span><br><span class="line"><span class="keyword">install</span>(TARGETS MathFunctions DESTINATION lib)</span><br><span class="line"><span class="keyword">install</span>(FILES MathFunctions.h DESTINATION <span class="keyword">include</span>)</span><br></pre></td></tr></table></figure>

<p>接下来,更新 <code>MathFunctions/mysqrt.cxx</code>以使用<code>mathfunctions</code> 和 <code>detail</code>名字空间:</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"MathFunctions.h"</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">// include the generated table</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"Table.h"</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> mathfunctions &#123;</span><br><span class="line"><span class="keyword">namespace</span> detail &#123;</span><br><span class="line"><span class="comment">// a hack square root calculation using simple operations</span></span><br><span class="line"><span class="function"><span class="keyword">double</span> <span class="title">mysqrt</span><span class="params">(<span class="keyword">double</span> x)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="keyword">if</span> (x &lt;= <span class="number">0</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// use the table to help find an initial value</span></span><br><span class="line">  <span class="keyword">double</span> result = x;</span><br><span class="line">  <span class="keyword">if</span> (x &gt;= <span class="number">1</span> &amp;&amp; x &lt; <span class="number">10</span>) &#123;</span><br><span class="line">    <span class="built_in">std</span>::<span class="built_in">cout</span> &lt;&lt; <span class="string">"Use the table to help find an initial value "</span> &lt;&lt; <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">    result = sqrtTable[<span class="keyword">static_cast</span>&lt;<span class="keyword">int</span>&gt;(x)];</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// do ten iterations</span></span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">10</span>; ++i) &#123;</span><br><span class="line">    <span class="keyword">if</span> (result &lt;= <span class="number">0</span>) &#123;</span><br><span class="line">      result = <span class="number">0.1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">double</span> delta = x - (result * result);</span><br><span class="line">    result = result + <span class="number">0.5</span> * delta / result;</span><br><span class="line">    <span class="built_in">std</span>::<span class="built_in">cout</span> &lt;&lt; <span class="string">"Computing sqrt of "</span> &lt;&lt; x &lt;&lt; <span class="string">" to be "</span> &lt;&lt; result &lt;&lt; <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>我们还需要在<code>tutorial.cxx</code>中做一些修改，使其不再使用<code>USE_MYMATH</code>:</p>
<ol>
<li>总是包含<code>MathFunctions.h</code></li>
<li>总是使用<code>mathfunctions::sqrt</code></li>
<li>不包括<code>cmath</code></li>
</ol>
<p>最后，更新<code>MathFunctions/MathFunctions.h</code>以使用dll导出(dll export)定义:</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">if</span> defined(_WIN32)</span></span><br><span class="line"><span class="meta">#  <span class="meta-keyword">if</span> defined(EXPORTING_MYMATH)</span></span><br><span class="line"><span class="meta">#    <span class="meta-keyword">define</span> DECLSPEC __declspec(dllexport)</span></span><br><span class="line"><span class="meta">#  <span class="meta-keyword">else</span></span></span><br><span class="line"><span class="meta">#    <span class="meta-keyword">define</span> DECLSPEC __declspec(dllimport)</span></span><br><span class="line"><span class="meta">#  <span class="meta-keyword">endif</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">else</span> <span class="comment">// non windows</span></span></span><br><span class="line"><span class="meta">#  <span class="meta-keyword">define</span> DECLSPEC</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> mathfunctions &#123;</span><br><span class="line"><span class="function"><span class="keyword">double</span> DECLSPEC <span class="title">sqrt</span><span class="params">(<span class="keyword">double</span> x)</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>此时，如果您构建所有内容，您将注意到链接(linking)失败了，因为我们正在将一个没有位置无关代码的静态库与一个具有位置无关代码的库组合在一起。解决方案是显式地将SqrtLibrary的<code>POSITION_INDEPENDENT_CODE</code>目标属性设置为True，无论构建类型如何。</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># state that SqrtLibrary need PIC when the default is shared libraries</span></span><br><span class="line"><span class="keyword">set_target_properties</span>(SqrtLibrary PROPERTIES</span><br><span class="line">                      POSITION_INDEPENDENT_CODE <span class="variable">$&#123;BUILD_SHARED_LIBS&#125;</span></span><br><span class="line">                      )</span><br><span class="line"></span><br><span class="line"><span class="keyword">target_link_libraries</span>(MathFunctions PRIVATE SqrtLibrary)</span><br></pre></td></tr></table></figure>

<p>练习:我们修改了<code>MathFunctions.h</code>以使用dll导出定义。使用CMake文档，你能找到一个帮助模块来简化它吗?</p>
<h2 id="第10步-添加生成器表达式-Adding-Generator-Expressions-Step-10"><a href="#第10步-添加生成器表达式-Adding-Generator-Expressions-Step-10" class="headerlink" title="第10步 添加生成器表达式 Adding Generator Expressions (Step 10)"></a>第10步 添加生成器表达式 Adding Generator Expressions (Step 10)</h2><p>生成器表达式在构建过程中计算，以生成特定于每个构建配置的信息。</p>
<p>生成器表达式可以在许多目标属性的上下文中使用，比如<code>LINK_LIBRARIES</code>、<code>INCLUDE_DIRECTORY</code>、<code>COMPILE_DEFINITION</code>等。他们也可以用在给这些属性添加值的命令上，比如：<code>target_link_libraries()</code>、<code>target_include_directory()</code>、<code>target_compile_definitions()</code>等。</p>
<p>生成器表达式可用于条件链接、条件宏定义、条件头文件路径等。这些条件可能基于构建配置、目标属性、平台信息或其他可查询信息。</p>
<p>有不同类型的生成器表达式，包括：逻辑表达式、信息表达式和输出表达式(Logical, Informational, and Output expressions)。</p>
<p>逻辑表达式用于创建条件输出。基本表达式是0和1表达式。<code>$&lt;0:...&gt;</code>的结果是空字符串，<code>$&lt;1:...&gt;</code>的结果是“…”的内容。它们也可以嵌套。</p>
<p>生成器表达式通常用来按需添加编译标志，例如针对语言级别或警告的标志。一个好模式是把该信息关联到<code>INTERFACE</code>目标，以允许该信息传播。让我们首先构造一个<code>INTERFACE</code>目标，并指定所需的C++标准<code>11</code>，而不是使用<code>CMAKE_CXX_STANDARD</code>。<br>所以下面的代码:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># specify the C++ standard</span></span><br><span class="line"><span class="keyword">set</span>(CMAKE_CXX_STANDARD <span class="number">11</span>)</span><br><span class="line"><span class="keyword">set</span>(CMAKE_CXX_STANDARD_REQUIRED <span class="keyword">True</span>)</span><br></pre></td></tr></table></figure>
<p>将改为:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">add_library</span>(tutorial_compiler_flags INTERFACE)</span><br><span class="line"><span class="keyword">target_compile_features</span>(tutorial_compiler_flags INTERFACE cxx_std_11)</span><br></pre></td></tr></table></figure>

<p>接下来，我们为项目添加所需的编译器警告标志。由于警告标志因不同编译器而不同，我们使用<code>COMPILE_LANG_AND_ID</code>生成器表达式来控制在给定语言和一组编译器ID中使用哪些标志，如下所示:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">set</span>(gcc_like_cxx <span class="string">"$&lt;COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU&gt;"</span>)</span><br><span class="line"><span class="keyword">set</span>(msvc_cxx <span class="string">"$&lt;COMPILE_LANG_AND_ID:CXX,MSVC&gt;"</span>)</span><br><span class="line"><span class="keyword">target_compile_options</span>(tutorial_compiler_flags INTERFACE</span><br><span class="line">  <span class="string">"$&lt;$&#123;gcc_like_cxx&#125;:$&lt;BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused&gt;&gt;"</span></span><br><span class="line">  <span class="string">"$&lt;$&#123;msvc_cxx&#125;:$&lt;BUILD_INTERFACE:-W3&gt;&gt;"</span></span><br><span class="line">)</span><br></pre></td></tr></table></figure>
<p>我们可以看到，警告标志被封装在<code>BUILD_INTERFACE</code>条件中。这样做可以使已安装项目的使用者不会继承我们的警告标志。</p>
<p>练习: 修改<code>MathFunctions/CMakeLists.txt</code>，使所有目标都有一个<code>target_link_libraries()</code>调用<code>tutorial_compiler_flags</code>。</p>
<h2 id="第11步-添加导出配置-Adding-Export-Configuration-Step-11"><a href="#第11步-添加导出配置-Adding-Export-Configuration-Step-11" class="headerlink" title="第11步 添加导出配置 Adding Export Configuration (Step 11)"></a>第11步 添加导出配置 Adding Export Configuration (Step 11)</h2><p>在安装和测试(第4步)的教程中，我们为CMake添加了安装库和项目头文件的功能。在构建安装程序(第7步)中，我们添加了打包这些信息的功能，以便将其分发给其他人。</p>
<p>下一步是添加必要的信息，以便其他CMake项目可以通过构建目录、本地安装或安装包来使用我们的项目。</p>
<p>第一步是更新<code>install(TARGETS)</code>命令，不仅要指定<code>DESTINATION</code>，还要指定<code>EXPORT</code>。<code>EXPORT</code>关键字生成并安装一个CMake文件，该文件包含从安装树导入install命令中列出的所有目标的代码。因此，让我们通过更新<code>MathFunctions/CMakeLists.txt</code>中的install命令来显式地<code>EXPORT</code>MathFunctions库，如下所示:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">install</span>(TARGETS MathFunctions tutorial_compiler_flags</span><br><span class="line">        DESTINATION lib</span><br><span class="line">        <span class="keyword">EXPORT</span> MathFunctionsTargets)</span><br><span class="line"><span class="keyword">install</span>(FILES MathFunctions.h DESTINATION <span class="keyword">include</span>)</span><br></pre></td></tr></table></figure>

<p>现在, 我们已经导出了mathfunction，我们还需要显式地安装生成的<code>MathFunctionsTargets.cmake</code>文件。这是通过在顶层<code>CMakeLists.txt</code>的末尾添加以下内容来实现的:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">install</span>(<span class="keyword">EXPORT</span> MathFunctionsTargets</span><br><span class="line">  <span class="keyword">FILE</span> MathFunctionsTargets.cmake</span><br><span class="line">  DESTINATION lib/cmake/MathFunctions</span><br><span class="line">)</span><br></pre></td></tr></table></figure>

<p>此时，您应该尝试运行CMake。如果一切设置正确，你会看到，CMake将产生一个错误，看起来像:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Target &quot;MathFunctions&quot; INTERFACE_INCLUDE_DIRECTORIES property contains</span><br><span class="line">path:</span><br><span class="line"></span><br><span class="line">  &quot;&#x2F;Users&#x2F;robert&#x2F;Documents&#x2F;CMakeClass&#x2F;Tutorial&#x2F;Step11&#x2F;MathFunctions&quot;</span><br><span class="line"></span><br><span class="line">which is prefixed in the source directory.</span><br></pre></td></tr></table></figure>

<p>CMake试图说明的是，在生成导出信息的过程中，它将导出一个与当前机器紧密相连的路径，而这个路径在其他机器上是无效的。解决方案是，更新MathFunctions的 <code>target_include_directories()</code>，使它明白在构建目录内和<code>install / package</code>中，需要不同的<code>INTERFACE</code>位置。这意味着将mathfunction的<code>target_include_directories()</code>调用转换为如下形式:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">target_include_directories</span>(MathFunctions</span><br><span class="line">                           INTERFACE</span><br><span class="line">                            $&lt;BUILD_INTERFACE:<span class="variable">$&#123;CMAKE_CURRENT_SOURCE_DIR&#125;</span>&gt;</span><br><span class="line">                            $&lt;INSTALL_INTERFACE:<span class="keyword">include</span>&gt;</span><br><span class="line">                           )</span><br></pre></td></tr></table></figure>

<p>一旦更新这个，我们可以重新运行CMake并验证它不再发出警告。</p>
<p>此时，CMake已经能正确地打包需要的目标信息了，但是我们仍然需要生成<code>MathFunctionsConfig.cmake</code>,这样，CMake的<code>find_package()</code>命令才能找到我们的项目。因此，让我们继续向项目的顶层添加一个名为<code>Config.cmake.in</code>的新文件，内容如下:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">@PACKAGE_INIT@</span><br><span class="line"></span><br><span class="line"><span class="keyword">include</span> ( <span class="string">"$&#123;CMAKE_CURRENT_LIST_DIR&#125;/MathFunctionsTargets.cmake"</span> )</span><br></pre></td></tr></table></figure>

<p>然后，为了正确配置和安装该文件，在顶层<code>CMakeLists.txt</code>的末尾添加以下内容:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">install</span>(<span class="keyword">EXPORT</span> MathFunctionsTargets</span><br><span class="line">  <span class="keyword">FILE</span> MathFunctionsTargets.cmake</span><br><span class="line">  DESTINATION lib/cmake/MathFunctions</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="keyword">include</span>(CMakePackageConfigHelpers)</span><br><span class="line"><span class="comment"># generate the config file that is includes the exports</span></span><br><span class="line">configure_package_config_file(<span class="variable">$&#123;CMAKE_CURRENT_SOURCE_DIR&#125;</span>/Config.cmake.in</span><br><span class="line">  <span class="string">"$&#123;CMAKE_CURRENT_BINARY_DIR&#125;/MathFunctionsConfig.cmake"</span></span><br><span class="line">  INSTALL_DESTINATION <span class="string">"lib/cmake/example"</span></span><br><span class="line">  NO_SET_AND_CHECK_MACRO</span><br><span class="line">  NO_CHECK_REQUIRED_COMPONENTS_MACRO</span><br><span class="line">  )</span><br><span class="line"><span class="comment"># generate the version file for the config file</span></span><br><span class="line">write_basic_package_version_file(</span><br><span class="line">  <span class="string">"$&#123;CMAKE_CURRENT_BINARY_DIR&#125;/MathFunctionsConfigVersion.cmake"</span></span><br><span class="line">  VERSION <span class="string">"$&#123;Tutorial_VERSION_MAJOR&#125;.$&#123;Tutorial_VERSION_MINOR&#125;"</span></span><br><span class="line">  COMPATIBILITY AnyNewerVersion</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment"># install the configuration file</span></span><br><span class="line"><span class="keyword">install</span>(FILES</span><br><span class="line">  <span class="variable">$&#123;CMAKE_CURRENT_BINARY_DIR&#125;</span>/MathFunctionsConfig.cmake</span><br><span class="line">  DESTINATION lib/cmake/MathFunctions</span><br><span class="line">  )</span><br></pre></td></tr></table></figure>

<p>此时，我们已经为我们的项目生成了一个可以在项目安装或打包以后重定位的CMake配置。如果我们希望我们的项目也可以从一个构建目录中使用，我们只需要在顶层<code>CMakeLists.txt</code>的结尾添加以下内容:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span>(<span class="keyword">EXPORT</span> MathFunctionsTargets</span><br><span class="line">  <span class="keyword">FILE</span> <span class="string">"$&#123;CMAKE_CURRENT_BINARY_DIR&#125;/MathFunctionsTargets.cmake"</span></span><br><span class="line">)</span><br></pre></td></tr></table></figure>

<p>通过这个导出调用，我们现在生成一个<code>Targets.cmake</code>，使得在构建目录中配置生成的<code>MathFunctionsConfig.cmake</code>可以被其他项目使用，而不需要安装它。</p>
<h2 id="第12步-打包调试版和发布版-Packaging-Debug-and-Release-Step-12"><a href="#第12步-打包调试版和发布版-Packaging-Debug-and-Release-Step-12" class="headerlink" title="第12步 打包调试版和发布版 Packaging Debug and Release (Step 12)"></a>第12步 打包调试版和发布版 Packaging Debug and Release (Step 12)</h2><p>注意:此示例对单配置生成器有效，对多配置生成器(例如Visual Studio)无效。</p>
<p>默认情况下，CMake模型是一个构建目录只包含一个配置：Debug、Release、MinSizeRel或RelWithDebInfo。但是，可以设置CPack来打包多个构建目录，并构造一个包含同一项目多个配置的包。</p>
<p>首先，我们希望确保调试和发布版本使用不同的名称来表示将要安装的可执行文件和库。让我们使用<code>d</code>作为调试可执行文件和库的后缀。</p>
<p>在顶层<code>CMakeLists.txt</code>的开始设置<code>CMAKE_DEBUG_POSTFIX</code>:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">set</span>(CMAKE_DEBUG_POSTFIX d)</span><br><span class="line"></span><br><span class="line"><span class="keyword">add_library</span>(tutorial_compiler_flags INTERFACE)</span><br></pre></td></tr></table></figure>

<p>以及可执行tutorial的<code>DEBUG_POSTFIX</code>属性:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">add_executable</span>(Tutorial tutorial.cxx)</span><br><span class="line"><span class="keyword">set_target_properties</span>(Tutorial PROPERTIES DEBUG_POSTFIX <span class="variable">$&#123;CMAKE_DEBUG_POSTFIX&#125;</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">target_link_libraries</span>(Tutorial PUBLIC MathFunctions)</span><br></pre></td></tr></table></figure>

<p>我们还将版本编号添加到MathFunctions库中。在<code>MathFunctions/CMakeLists.txt</code>，设置<code>VERSION</code>和<code>SOVERSION</code>属性:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">set_property</span>(<span class="keyword">TARGET</span> MathFunctions PROPERTY VERSION <span class="string">"1.0.0"</span>)</span><br><span class="line"><span class="keyword">set_property</span>(<span class="keyword">TARGET</span> MathFunctions PROPERTY SOVERSION <span class="string">"1"</span>)</span><br></pre></td></tr></table></figure>

<p>在<code>Step12</code>目录中，创建<code>build\debug</code>和<code>build\release</code>子目录。目录层次看起来像:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">- Step12</span><br><span class="line">  - build</span><br><span class="line">    - debug</span><br><span class="line">    - release</span><br></pre></td></tr></table></figure>

<p>现在我们需要生成<code>debug</code>和<code>release</code>版。我们可以使用<code>CMAKE_BUILD_TYPE</code>来设置配置类型:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">$ cd build&#x2F;debug</span><br><span class="line">$ cmake -DCMAKE_BUILD_TYPE&#x3D;Debug ..&#x2F;..</span><br><span class="line">$ cmake --build .</span><br><span class="line">$ cd ..&#x2F;release</span><br><span class="line">$ cmake -DCMAKE_BUILD_TYPE&#x3D;Release ..&#x2F;..</span><br><span class="line">$ cmake --build . --config Release</span><br></pre></td></tr></table></figure>

<p>现在<code>debug</code>和<code>release</code>版构建都完成了，我们可以使用一个自定义配置文件将两个构建打包到一个单独的发布中。在<code>Step12</code>目录中，创建一个名为<code>MultiCPackConfig.cmake</code>的文件。在这个文件中，首先包含由<code>cmake</code>可执行文件创建的默认配置文件。</p>
<p>接下来，使用<code>CPACK_INSTALL_CMAKE_PROJECTS</code>变量来指定安装哪些项目。在本例中，我们希望同时安装debug和release。</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">include</span>(<span class="string">"build/release/CPackConfig.cmake"</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">set</span>(CPACK_INSTALL_CMAKE_PROJECTS</span><br><span class="line">    <span class="string">"build/debug;Tutorial;ALL;/"</span></span><br><span class="line">    <span class="string">"build/release;Tutorial;ALL;/"</span></span><br><span class="line">    )</span><br></pre></td></tr></table></figure>

<p>从<code>Step12\build</code>目录运行<code>cpack</code>，并使用config选项指定我们的自定义配置文件:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cpack --config ..&#x2F;MultiCPackConfig.cmake</span><br></pre></td></tr></table></figure>
















<h2 id="备注"><a href="#备注" class="headerlink" title="备注"></a>备注</h2><h3 id="MAC配置cmake"><a href="#MAC配置cmake" class="headerlink" title="MAC配置cmake"></a>MAC配置cmake</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">brew install cmake</span><br><span class="line">REM ln –s 源文件 目标文件</span><br><span class="line">sudo ln -s &#x2F;usr&#x2F;local&#x2F;Cellar&#x2F;cmake&#x2F;3.14.4&#x2F;bin&#x2F;cmake &#x2F;usr&#x2F;local&#x2F;bin&#x2F;cmake</span><br></pre></td></tr></table></figure>

<h3 id="参考："><a href="#参考：" class="headerlink" title="参考："></a>参考：</h3><ul>
<li><a href="https://blog.csdn.net/weilianyishi/article/details/47002973?locationNum=3" target="_blank" rel="noopener">CMake 用法导览</a></li>
<li><a href="https://www.jianshu.com/p/7326f9167fae" target="_blank" rel="noopener">CMake 教程 Step by Step</a></li>
</ul>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://yao_yu.gitee.io/2020/05/11/CMake%E6%95%99%E7%A8%8B%E5%B0%8F%E7%BB%93/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="老树">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="大师之路">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2020/05/11/CMake%E6%95%99%E7%A8%8B%E5%B0%8F%E7%BB%93/" class="post-title-link" itemprop="url">CMake教程小结</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-05-11 17:36:01" itemprop="dateCreated datePublished" datetime="2020-05-11T17:36:01+08:00">2020-05-11</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2020-05-09 16:59:58" itemprop="dateModified" datetime="2020-05-09T16:59:58+08:00">2020-05-09</time>
              </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="CMake教程小结"><a href="#CMake教程小结" class="headerlink" title="CMake教程小结"></a>CMake教程小结</h1><p>[toc]</p>
<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>CMake教程通过一个示例项目, 逐步介绍了CMake构建系统的主要功能, 包括:</p>
<ol>
<li>生成执行程序</li>
<li>生成库(使用旧式CMake宏定义方法)</li>
<li>生成库(使用新式CMake宏定义方法–使用要求)</li>
<li>基于源代码的安装与测试</li>
<li>系统检测</li>
<li>添加自定义命令以及生成文件</li>
<li>构建安装程序</li>
<li>将测试结果提交到Kitware的公共指示板</li>
<li>混合静态和共享(动态)库</li>
<li>生成器表达式,条件判断</li>
<li><a href="https://cmake.org/cmake/help/latest/command/find_package.html#command:find_package" target="_blank" rel="noopener">find_package()</a>支持(添加导出配置)</li>
<li>将调试版和发行版打包在一起(win10试验没有成功)</li>
</ol>
<blockquote>
<p>注:</p>
<ol>
<li>示例项目目录在CMake源代码树的<code>Help\guide\tutorial</code>目录</li>
<li>本摘要主要关注CMake使用, 一些关于源代码的更改在请查看<a href="https://cmake.org/cmake/help/latest/guide/tutorial/index.html" target="_blank" rel="noopener">CMake教程</a></li>
<li>CMake教程示例代码,下一步的内容都是上一步的结果</li>
</ol>
</blockquote>
<h2 id="主要功能摘要"><a href="#主要功能摘要" class="headerlink" title="主要功能摘要"></a>主要功能摘要</h2><h3 id="1-生成执行程序"><a href="#1-生成执行程序" class="headerlink" title="1. 生成执行程序"></a>1. 生成执行程序</h3><p>本节示例展示了:</p>
<ul>
<li>生成执行程序的基本构建系统框架;</li>
<li>将一些CMake属性通过配置文件输出;</li>
<li>如何在目标中添加头文件搜索路径;</li>
<li>常规CMake命令行使用方式</li>
</ul>
<blockquote>
<p>注: 本节示例初始代码在示例目录的<code>Step1</code>子目录, 成果在<code>Step2</code>子目录</p>
</blockquote>
<h4 id="核心代码"><a href="#核心代码" class="headerlink" title="核心代码"></a>核心代码</h4><p>顶层目录的<strong>CMakeLists.txt</strong>内容如下:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 指定CMake最小版本</span></span><br><span class="line"><span class="keyword">cmake_minimum_required</span>(VERSION <span class="number">3.10</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置项目名称及版本号</span></span><br><span class="line"><span class="keyword">project</span>(Tutorial VERSION <span class="number">1.0</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 指定C++版本</span></span><br><span class="line"><span class="keyword">set</span>(CMAKE_CXX_STANDARD <span class="number">11</span>)</span><br><span class="line"><span class="keyword">set</span>(CMAKE_CXX_STANDARD_REQUIRED <span class="keyword">True</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 配置头文件, 将一些CMake属性值保存到源代码中</span></span><br><span class="line"><span class="keyword">configure_file</span>(TutorialConfig.h.in TutorialConfig.h)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 生成执行程序</span></span><br><span class="line"><span class="keyword">add_executable</span>(Tutorial tutorial.cxx)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 将项目输出目录(binary tree)添加到Tutorial目标的头文件搜索路径, 这样才能找到生成的TutorialConfig.h</span></span><br><span class="line"><span class="keyword">target_include_directories</span>(Tutorial PUBLIC</span><br><span class="line">                           <span class="string">"$&#123;PROJECT_BINARY_DIR&#125;"</span></span><br><span class="line">                           )</span><br></pre></td></tr></table></figure>

<p><strong>TutorialConfig.h.in</strong>内容如下:</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 接受CMake配置属性</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@</span></span><br></pre></td></tr></table></figure>

<h4 id="命令行使用示例"><a href="#命令行使用示例" class="headerlink" title="命令行使用示例"></a>命令行使用示例</h4><p>在项目目录下</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ mkdir build</span><br><span class="line">$ cd build</span><br><span class="line">$ cmake ..</span><br><span class="line">$ cmake --build .</span><br></pre></td></tr></table></figure>

<h3 id="2-生成库-旧式CMake"><a href="#2-生成库-旧式CMake" class="headerlink" title="2. 生成库(旧式CMake)"></a>2. 生成库(旧式CMake)</h3><p>在上一步的基础上, 本节示例展示了:</p>
<ul>
<li>生成库;</li>
<li>在项目中添加库;</li>
<li>使用可选项,并将可选项保存到配置文件中;</li>
<li>目标链接库的旧式方法;</li>
<li>目标包含库头文件目录的旧式方法;</li>
</ul>
<blockquote>
<p>注: 本节示例初始代码在示例目录的<code>Step2</code>子目录, 成果在<code>Step3</code>子目录</p>
</blockquote>
<h4 id="生成库"><a href="#生成库" class="headerlink" title="生成库"></a>生成库</h4><ol>
<li>创建库目录;</li>
<li>在库目录<strong>CMakeLists.txt</strong>中, 添加生成库命令如下:</li>
</ol>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 生成库</span></span><br><span class="line"><span class="keyword">add_library</span>(MathFunctions mysqrt.cxx)</span><br></pre></td></tr></table></figure>

<h4 id="其它核心代码"><a href="#其它核心代码" class="headerlink" title="其它核心代码"></a>其它核心代码</h4><p>项目<strong>CMakeLists.txt</strong>内容如下:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 指定CMake最小版本</span></span><br><span class="line"><span class="keyword">cmake_minimum_required</span>(VERSION <span class="number">3.10</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置项目名称及版本号</span></span><br><span class="line"><span class="keyword">project</span>(Tutorial VERSION <span class="number">1.0</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 指定C++版本</span></span><br><span class="line"><span class="keyword">set</span>(CMAKE_CXX_STANDARD <span class="number">11</span>)</span><br><span class="line"><span class="keyword">set</span>(CMAKE_CXX_STANDARD_REQUIRED <span class="keyword">True</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 是否使用自定义数学库可选项</span></span><br><span class="line"><span class="keyword">option</span>(USE_MYMATH <span class="string">"Use tutorial provided math implementation"</span> <span class="keyword">ON</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 配置头文件, 将一些CMake属性值保存到源代码中</span></span><br><span class="line"><span class="keyword">configure_file</span>(TutorialConfig.h.in TutorialConfig.h)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 添加自定义数学库</span></span><br><span class="line"><span class="keyword">if</span>(USE_MYMATH)</span><br><span class="line">  <span class="keyword">add_subdirectory</span>(MathFunctions)</span><br><span class="line">  <span class="keyword">list</span>(APPEND EXTRA_LIBS MathFunctions)</span><br><span class="line">  <span class="keyword">list</span>(APPEND EXTRA_INCLUDES <span class="string">"$&#123;PROJECT_SOURCE_DIR&#125;/MathFunctions"</span>)</span><br><span class="line"><span class="keyword">endif</span>()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 生成执行程序</span></span><br><span class="line"><span class="keyword">add_executable</span>(Tutorial tutorial.cxx)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Tutorial目标链接相关库</span></span><br><span class="line"><span class="keyword">target_link_libraries</span>(Tutorial PUBLIC <span class="variable">$&#123;EXTRA_LIBS&#125;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Tutorial目标添加头文件搜索路径(项目生成目录,其它头文件目录)</span></span><br><span class="line"><span class="keyword">target_include_directories</span>(Tutorial PUBLIC</span><br><span class="line">                           <span class="string">"$&#123;PROJECT_BINARY_DIR&#125;"</span></span><br><span class="line">                           <span class="variable">$&#123;EXTRA_INCLUDES&#125;</span></span><br><span class="line">                           )</span><br></pre></td></tr></table></figure>

<p><strong>TutorialConfig.h.in</strong>内容如下:</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 接受CMake配置属性</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@</span></span><br><span class="line"><span class="meta">#cmakedefine USE_MYMATH</span></span><br></pre></td></tr></table></figure>

<h3 id="3-生成库-新式CMake"><a href="#3-生成库-新式CMake" class="headerlink" title="3. 生成库(新式CMake)"></a>3. 生成库(新式CMake)</h3><p>在上一步的基础上, 本节示例展示了:</p>
<ul>
<li>在库中使用<strong>INTERFACE</strong>;</li>
<li>在项目中添加库;</li>
<li>使用可选项,并将可选项保存到配置文件中;</li>
<li>目标链接库的旧式方法;</li>
<li>目标包含库头文件目录的旧式方法;</li>
</ul>
<blockquote>
<p>注: 本节示例初始代码在示例目录的<code>Step3</code>子目录, 成果在<code>Step4</code>子目录</p>
</blockquote>
<h4 id="核心代码更改"><a href="#核心代码更改" class="headerlink" title="核心代码更改"></a>核心代码更改</h4><p><strong>库目录CMakeLists.txt</strong>内容如下:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 生成库</span></span><br><span class="line"><span class="keyword">add_library</span>(MathFunctions mysqrt.cxx)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置目录头文件搜索路径. INTERFACE是使用者需要, 库本身不需要</span></span><br><span class="line"><span class="comment"># 通过INTERFACE可以将头文件搜索路径转递给使用者</span></span><br><span class="line"><span class="keyword">target_include_directories</span>(MathFunctions</span><br><span class="line">          INTERFACE <span class="variable">$&#123;CMAKE_CURRENT_SOURCE_DIR&#125;</span></span><br><span class="line">          )</span><br></pre></td></tr></table></figure>

<p><strong>项目CMakeLists.txt</strong>删除了<em>EXTRA_INCLUDES</em>相关代码, 变化如下:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 指定CMake最小版本</span></span><br><span class="line"><span class="keyword">cmake_minimum_required</span>(VERSION <span class="number">3.10</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置项目名称及版本号</span></span><br><span class="line"><span class="keyword">project</span>(Tutorial VERSION <span class="number">1.0</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 指定C++版本</span></span><br><span class="line"><span class="keyword">set</span>(CMAKE_CXX_STANDARD <span class="number">11</span>)</span><br><span class="line"><span class="keyword">set</span>(CMAKE_CXX_STANDARD_REQUIRED <span class="keyword">True</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 是否使用自定义数学库可选项</span></span><br><span class="line"><span class="keyword">option</span>(USE_MYMATH <span class="string">"Use tutorial provided math implementation"</span> <span class="keyword">ON</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 配置头文件, 将一些CMake属性值保存到源代码中</span></span><br><span class="line"><span class="keyword">configure_file</span>(TutorialConfig.h.in TutorialConfig.h)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 添加自定义数学库</span></span><br><span class="line"><span class="keyword">if</span>(USE_MYMATH)</span><br><span class="line">  <span class="keyword">add_subdirectory</span>(MathFunctions)</span><br><span class="line">  <span class="keyword">list</span>(APPEND EXTRA_LIBS MathFunctions)</span><br><span class="line"><span class="keyword">endif</span>()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 生成执行程序</span></span><br><span class="line"><span class="keyword">add_executable</span>(Tutorial tutorial.cxx)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Tutorial目标链接相关库(此代码会使用新式CMake方法传递库属性)</span></span><br><span class="line"><span class="keyword">target_link_libraries</span>(Tutorial PUBLIC <span class="variable">$&#123;EXTRA_LIBS&#125;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Tutorial目标添加头文件搜索路径</span></span><br><span class="line"><span class="keyword">target_include_directories</span>(Tutorial PUBLIC</span><br><span class="line">                           <span class="string">"$&#123;PROJECT_BINARY_DIR&#125;"</span></span><br><span class="line">                           )</span><br></pre></td></tr></table></figure>

<h3 id="4-基于源代码的安装与测试"><a href="#4-基于源代码的安装与测试" class="headerlink" title="4. 基于源代码的安装与测试"></a>4. 基于源代码的安装与测试</h3><p>在上一步的基础上, 本节示例展示了:</p>
<ul>
<li>使用基于源代码的安装规则(install);</li>
<li>使用测试;</li>
</ul>
<blockquote>
<p>注: 本节示例初始代码在示例目录的<code>Step4</code>子目录, 成果在<code>Step5</code>子目录</p>
</blockquote>
<h4 id="核心代码更改-1"><a href="#核心代码更改-1" class="headerlink" title="核心代码更改"></a>核心代码更改</h4><p><strong>库目录CMakeLists.txt</strong>变化如下:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 生成库</span></span><br><span class="line"><span class="keyword">add_library</span>(MathFunctions mysqrt.cxx)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置目录头文件搜索路径. INTERFACE是使用者需要, 库本身不需要</span></span><br><span class="line"><span class="comment"># 通过INTERFACE可以将头文件搜索路径转递给使用者</span></span><br><span class="line"><span class="keyword">target_include_directories</span>(MathFunctions</span><br><span class="line">          INTERFACE <span class="variable">$&#123;CMAKE_CURRENT_SOURCE_DIR&#125;</span></span><br><span class="line">          )</span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装规则</span></span><br><span class="line"><span class="keyword">install</span>(TARGETS MathFunctions DESTINATION lib)</span><br><span class="line"><span class="keyword">install</span>(FILES MathFunctions.h DESTINATION <span class="keyword">include</span>)</span><br></pre></td></tr></table></figure>

<p><strong>项目CMakeLists.txt</strong>新增了安装与测试相关代码, 变化如下:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 指定CMake最小版本</span></span><br><span class="line"><span class="keyword">cmake_minimum_required</span>(VERSION <span class="number">3.10</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置项目名称及版本号</span></span><br><span class="line"><span class="keyword">project</span>(Tutorial VERSION <span class="number">1.0</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 指定C++版本</span></span><br><span class="line"><span class="keyword">set</span>(CMAKE_CXX_STANDARD <span class="number">11</span>)</span><br><span class="line"><span class="keyword">set</span>(CMAKE_CXX_STANDARD_REQUIRED <span class="keyword">True</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 是否使用自定义数学库可选项</span></span><br><span class="line"><span class="keyword">option</span>(USE_MYMATH <span class="string">"Use tutorial provided math implementation"</span> <span class="keyword">ON</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 配置头文件, 将一些CMake属性值保存到源代码中</span></span><br><span class="line"><span class="keyword">configure_file</span>(TutorialConfig.h.in TutorialConfig.h)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 添加自定义数学库</span></span><br><span class="line"><span class="keyword">if</span>(USE_MYMATH)</span><br><span class="line">  <span class="keyword">add_subdirectory</span>(MathFunctions)</span><br><span class="line">  <span class="keyword">list</span>(APPEND EXTRA_LIBS MathFunctions)</span><br><span class="line"><span class="keyword">endif</span>()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 生成执行程序</span></span><br><span class="line"><span class="keyword">add_executable</span>(Tutorial tutorial.cxx)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Tutorial目标链接相关库(此代码会使用新式CMake方法传递库属性)</span></span><br><span class="line"><span class="keyword">target_link_libraries</span>(Tutorial PUBLIC <span class="variable">$&#123;EXTRA_LIBS&#125;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Tutorial目标添加头文件搜索路径</span></span><br><span class="line"><span class="keyword">target_include_directories</span>(Tutorial PUBLIC</span><br><span class="line">                           <span class="string">"$&#123;PROJECT_BINARY_DIR&#125;"</span></span><br><span class="line">                           )</span><br><span class="line"></span><br><span class="line"><span class="comment"># 添加安装目标</span></span><br><span class="line"><span class="keyword">install</span>(TARGETS Tutorial DESTINATION bin)</span><br><span class="line"><span class="keyword">install</span>(FILES <span class="string">"$&#123;PROJECT_BINARY_DIR&#125;/TutorialConfig.h"</span></span><br><span class="line">  DESTINATION <span class="keyword">include</span></span><br><span class="line">  )</span><br><span class="line"></span><br><span class="line"><span class="comment"># 开启测试</span></span><br><span class="line"><span class="keyword">enable_testing</span>()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 验证Tutorial正常运行</span></span><br><span class="line"><span class="keyword">add_test</span>(NAME Runs <span class="keyword">COMMAND</span> Tutorial <span class="number">25</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 验证Tutorial的使用方法提示</span></span><br><span class="line"><span class="keyword">add_test</span>(NAME Usage <span class="keyword">COMMAND</span> Tutorial)</span><br><span class="line"><span class="keyword">set_tests_properties</span>(Usage</span><br><span class="line">  PROPERTIES PASS_REGULAR_EXPRESSION <span class="string">"Usage:.*number"</span></span><br><span class="line">  )</span><br><span class="line"></span><br><span class="line"><span class="comment"># 定义函数以简化测试添加</span></span><br><span class="line"><span class="keyword">function</span>(do_test <span class="keyword">target</span> arg result)</span><br><span class="line">  <span class="keyword">add_test</span>(NAME Comp<span class="variable">$&#123;arg&#125;</span> <span class="keyword">COMMAND</span> <span class="variable">$&#123;target&#125;</span> <span class="variable">$&#123;arg&#125;</span>)</span><br><span class="line">  <span class="keyword">set_tests_properties</span>(Comp<span class="variable">$&#123;arg&#125;</span></span><br><span class="line">    PROPERTIES PASS_REGULAR_EXPRESSION <span class="variable">$&#123;result&#125;</span></span><br><span class="line">    )</span><br><span class="line"><span class="keyword">endfunction</span>(do_test)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 批量添加基于结果的测试</span></span><br><span class="line">do_test(Tutorial <span class="number">4</span> <span class="string">"4 is 2"</span>)</span><br><span class="line">do_test(Tutorial <span class="number">9</span> <span class="string">"9 is 3"</span>)</span><br><span class="line">do_test(Tutorial <span class="number">5</span> <span class="string">"5 is 2.236"</span>)</span><br><span class="line">do_test(Tutorial <span class="number">7</span> <span class="string">"7 is 2.645"</span>)</span><br><span class="line">do_test(Tutorial <span class="number">25</span> <span class="string">"25 is 5"</span>)</span><br><span class="line">do_test(Tutorial -<span class="number">25</span> <span class="string">"-25 is [-nan|nan|0]"</span>)</span><br><span class="line">do_test(Tutorial <span class="number">0.0001</span> <span class="string">"0.0001 is 0.01"</span>)</span><br></pre></td></tr></table></figure>

<h4 id="命令行使用示例-1"><a href="#命令行使用示例-1" class="headerlink" title="命令行使用示例"></a>命令行使用示例</h4><p>将调试版<strong>安装</strong>到<em>D:\Temp2\ttt\debug</em></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">$ mkdir build</span><br><span class="line">$ cd build</span><br><span class="line">$ cmake ..</span><br><span class="line">生成并安装调试版</span><br><span class="line">$ cmake --build .</span><br><span class="line">$ cmake --install . --prefix D:\Temp2\ttt\debug --config Debug</span><br><span class="line">生成并安装发行版</span><br><span class="line">$ cmake --build . -- config Release</span><br><span class="line">$ cmake --install . --prefix D:\Temp2\ttt\Release --config Release</span><br></pre></td></tr></table></figure>

<p><strong>win10 VS2019 测试</strong></p>
<p>在<strong>build</strong>目录测试应用程序</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">$ mkdir build</span><br><span class="line">$ cd build</span><br><span class="line">$ cmake ..</span><br><span class="line">生成并测试调试版</span><br><span class="line">$ cmake --build .</span><br><span class="line">$ ctest -C Debug [-vv]</span><br><span class="line">生成并测试发行版</span><br><span class="line">$ cmake --build . -- config Release</span><br><span class="line">$ ctest -C Release [-vv]</span><br></pre></td></tr></table></figure>


<h3 id="5-系统检测"><a href="#5-系统检测" class="headerlink" title="5. 系统检测"></a>5. 系统检测</h3><p>在上一步的基础上, 本节示例展示了:</p>
<ul>
<li>CMake系统功能检测, 以判断平台是否支持特定功能;</li>
<li>目标编译定义(宏定义);</li>
</ul>
<blockquote>
<p>注1: 本节示例初始代码在示例目录的<code>Step5</code>子目录, 成果在<code>Step6</code>子目录<br>注2: 在win10下测试失败, 没有发现log,exp函数</p>
</blockquote>
<h4 id="核心代码更改-2"><a href="#核心代码更改-2" class="headerlink" title="核心代码更改"></a>核心代码更改</h4><p><strong>库目录CMakeLists.txt</strong>变化如下:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 生成库</span></span><br><span class="line"><span class="keyword">add_library</span>(MathFunctions mysqrt.cxx)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置目录头文件搜索路径. INTERFACE是使用者需要, 库本身不需要</span></span><br><span class="line"><span class="comment"># 通过INTERFACE可以将头文件搜索路径转递给使用者</span></span><br><span class="line"><span class="keyword">target_include_directories</span>(MathFunctions</span><br><span class="line">          INTERFACE <span class="variable">$&#123;CMAKE_CURRENT_SOURCE_DIR&#125;</span></span><br><span class="line">          )</span><br><span class="line"></span><br><span class="line"><span class="comment"># 检测系统是否支持log,exp函数?</span></span><br><span class="line"><span class="keyword">include</span>(CheckSymbolExists)</span><br><span class="line"><span class="keyword">set</span>(CMAKE_REQUIRED_LIBRARIES <span class="string">"m"</span>)</span><br><span class="line">check_symbol_exists(log <span class="string">"math.h"</span> HAVE_LOG)</span><br><span class="line">check_symbol_exists(exp <span class="string">"math.h"</span> HAVE_EXP)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span>(HAVE_LOG <span class="keyword">AND</span> HAVE_EXP)</span><br><span class="line">  <span class="comment"># 目标宏定义</span></span><br><span class="line">  <span class="keyword">target_compile_definitions</span>(MathFunctions</span><br><span class="line">                             PRIVATE <span class="string">"HAVE_LOG"</span> <span class="string">"HAVE_EXP"</span>)</span><br><span class="line"><span class="keyword">endif</span>()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装规则</span></span><br><span class="line"><span class="keyword">install</span>(TARGETS MathFunctions DESTINATION lib)</span><br><span class="line"><span class="keyword">install</span>(FILES MathFunctions.h DESTINATION <span class="keyword">include</span>)</span><br></pre></td></tr></table></figure>

<h3 id="6-添加自定义命令以及生成文件"><a href="#6-添加自定义命令以及生成文件" class="headerlink" title="6. 添加自定义命令以及生成文件"></a>6. 添加自定义命令以及生成文件</h3><p>在上一步的基础上, 本节示例展示了:</p>
<ul>
<li>CMake使用命令;</li>
<li>使用生成文件;</li>
</ul>
<blockquote>
<p>注: 本节示例初始代码在示例目录的<code>Step6</code>子目录, 成果在<code>Step7</code>子目录</p>
</blockquote>
<h4 id="核心代码更改-3"><a href="#核心代码更改-3" class="headerlink" title="核心代码更改"></a>核心代码更改</h4><p><strong>库目录CMakeLists.txt</strong>变化如下:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 首先生成一个用于产生预定义值表源代码的执行程序</span></span><br><span class="line"><span class="keyword">add_executable</span>(MakeTable MakeTable.cxx)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 添加自定义命令以产生源代码(依赖于MakeTable目标)</span></span><br><span class="line"><span class="keyword">add_custom_command</span>(</span><br><span class="line">  OUTPUT <span class="variable">$&#123;CMAKE_CURRENT_BINARY_DIR&#125;</span>/Table.h</span><br><span class="line">  <span class="keyword">COMMAND</span> MakeTable <span class="variable">$&#123;CMAKE_CURRENT_BINARY_DIR&#125;</span>/Table.h</span><br><span class="line">  DEPENDS MakeTable</span><br><span class="line">  )</span><br><span class="line"></span><br><span class="line"><span class="comment"># 生成主库(包含上一步中生成的预定义值表源代码)</span></span><br><span class="line"><span class="keyword">add_library</span>(MathFunctions</span><br><span class="line">            mysqrt.cxx</span><br><span class="line">            <span class="variable">$&#123;CMAKE_CURRENT_BINARY_DIR&#125;</span>/Table.h</span><br><span class="line">            )</span><br><span class="line"></span><br><span class="line"><span class="comment"># 通过INTERFACE向使用者传播头文件搜索路径</span></span><br><span class="line"><span class="comment"># 通过PRIVATE定义目标内部使用头文件搜索路径</span></span><br><span class="line"><span class="keyword">target_include_directories</span>(MathFunctions</span><br><span class="line">          INTERFACE <span class="variable">$&#123;CMAKE_CURRENT_SOURCE_DIR&#125;</span></span><br><span class="line">          PRIVATE <span class="variable">$&#123;CMAKE_CURRENT_BINARY_DIR&#125;</span></span><br><span class="line">          )</span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装规则</span></span><br><span class="line"><span class="keyword">install</span>(TARGETS MathFunctions DESTINATION lib)</span><br><span class="line"><span class="keyword">install</span>(FILES MathFunctions.h DESTINATION <span class="keyword">include</span>)</span><br></pre></td></tr></table></figure>


<h3 id="7-构建安装程序"><a href="#7-构建安装程序" class="headerlink" title="7. 构建安装程序"></a>7. 构建安装程序</h3><p>在上一步的基础上, 本节示例展示了:</p>
<ul>
<li>制作安装包;</li>
</ul>
<blockquote>
<p>注1: 本节示例初始代码在示例目录的<code>Step7</code>子目录, 成果在<code>Step8</code>子目录<br>注2: 为测试需要, 在win10上, 首先安装NSIS(Nulsoft Install System).</p>
</blockquote>
<h4 id="核心代码更改-4"><a href="#核心代码更改-4" class="headerlink" title="核心代码更改"></a>核心代码更改</h4><p><strong>顶层目录CMakeLists.txt</strong>末尾添加如下内容即可:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 设置安装器</span></span><br><span class="line"><span class="keyword">include</span>(InstallRequiredSystemLibraries)</span><br><span class="line"><span class="keyword">set</span>(CPACK_RESOURCE_FILE_LICENSE <span class="string">"$&#123;CMAKE_CURRENT_SOURCE_DIR&#125;/License.txt"</span>)</span><br><span class="line"><span class="keyword">set</span>(CPACK_PACKAGE_VERSION_MAJOR <span class="string">"$&#123;Tutorial_VERSION_MAJOR&#125;"</span>)</span><br><span class="line"><span class="keyword">set</span>(CPACK_PACKAGE_VERSION_MINOR <span class="string">"$&#123;Tutorial_VERSION_MINOR&#125;"</span>)</span><br><span class="line"><span class="keyword">include</span>(CPack)</span><br></pre></td></tr></table></figure>

<h4 id="命令行使用示例-2"><a href="#命令行使用示例-2" class="headerlink" title="命令行使用示例"></a>命令行使用示例</h4><p>在项目目录下</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">$ mkdir build</span><br><span class="line">$ cd build</span><br><span class="line">$ cmake ..</span><br><span class="line">$ cmake --build .</span><br><span class="line">VS generator 注意：目录不能含有中文</span><br><span class="line">生成发行版安装包(Tutorial-1.0-win64.exe)</span><br><span class="line">$ cmake --build . --target PACKAGE --config Release</span><br><span class="line">生成调试版安装包(Tutorial-1.0-win64.exe)</span><br><span class="line">$ cmake --build . --target PACKAGE --config Debug</span><br></pre></td></tr></table></figure>


<h3 id="8-将测试结果提交到Kitware的公共指示板"><a href="#8-将测试结果提交到Kitware的公共指示板" class="headerlink" title="8. 将测试结果提交到Kitware的公共指示板"></a>8. 将测试结果提交到Kitware的公共指示板</h3><p>在上一步的基础上, 本节示例展示了:</p>
<ul>
<li>将测试结果提交到Kitware的公共指示板;</li>
</ul>
<blockquote>
<p>注: 本节示例初始代码在示例目录的<code>Step8</code>子目录, 成果在<code>Step9</code>子目录</p>
</blockquote>
<h4 id="核心代码更改-5"><a href="#核心代码更改-5" class="headerlink" title="核心代码更改"></a>核心代码更改</h4><p><strong>顶层目录CMakeLists.txt</strong>将:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># enable testing</span></span><br><span class="line"><span class="keyword">enable_testing</span>()</span><br></pre></td></tr></table></figure>

<p>替换为:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># enable dashboard scripting</span></span><br><span class="line"><span class="keyword">include</span>(CTest)</span><br></pre></td></tr></table></figure>

<p>在顶层目录创建<strong>CTestConfig.cmake</strong>:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">set</span>(CTEST_PROJECT_NAME <span class="string">"CMakeTutorial"</span>)</span><br><span class="line"><span class="keyword">set</span>(CTEST_NIGHTLY_START_TIME <span class="string">"00:00:00 EST"</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">set</span>(CTEST_DROP_METHOD <span class="string">"http"</span>)</span><br><span class="line"><span class="keyword">set</span>(CTEST_DROP_SITE <span class="string">"my.cdash.org"</span>)</span><br><span class="line"><span class="keyword">set</span>(CTEST_DROP_LOCATION <span class="string">"/submit.php?project=CMakeTutorial"</span>)</span><br><span class="line"><span class="keyword">set</span>(CTEST_DROP_SITE_CDASH <span class="keyword">TRUE</span>)</span><br></pre></td></tr></table></figure>

<h4 id="命令行使用示例-3"><a href="#命令行使用示例-3" class="headerlink" title="命令行使用示例"></a>命令行使用示例</h4><p>在项目目录下</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">$ mkdir build</span><br><span class="line">$ cd build</span><br><span class="line">$ cmake ..</span><br><span class="line">VS generator 注意：目录不能含有中文</span><br><span class="line">发布发行版测试结果</span><br><span class="line">$ ctest [-VV] -C Release -D Experimental</span><br><span class="line">发布调试版测试结果</span><br><span class="line">$ ctest [-VV] -C Debug -D Experimental</span><br></pre></td></tr></table></figure>


<h3 id="9-混合静态和共享库"><a href="#9-混合静态和共享库" class="headerlink" title="9. 混合静态和共享库"></a>9. 混合静态和共享库</h3><p>在上一步的基础上, 本节示例展示了:</p>
<ul>
<li>在动态库中使用静态库</li>
<li>使用<code>BUILD_SHARED_LIBS</code>属性设置库默认生成类型(共享/非共享)(默认生成静态库);</li>
<li>使用目标宏定义(target_compile_definitions)设置windows动态库标志(<code>__declspec(dllexport),__declspec(dllimport)</code>)</li>
<li>在add_library中控制库生成类型[STATIC | SHARED | MODULE]</li>
</ul>
<blockquote>
<p>注: 本节示例初始代码在示例目录的<code>Step9</code>子目录, 成果在<code>Step10</code>子目录</p>
</blockquote>
<h4 id="核心代码更改-6"><a href="#核心代码更改-6" class="headerlink" title="核心代码更改"></a>核心代码更改</h4><p><strong>顶层CMakeLists.txt</strong>的起始部分更改为:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 指定CMake最小版本</span></span><br><span class="line"><span class="keyword">cmake_minimum_required</span>(VERSION <span class="number">3.10</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置项目名称及版本号</span></span><br><span class="line"><span class="keyword">project</span>(Tutorial VERSION <span class="number">1.0</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 指定C++版本</span></span><br><span class="line"><span class="keyword">set</span>(CMAKE_CXX_STANDARD <span class="number">11</span>)</span><br><span class="line"><span class="keyword">set</span>(CMAKE_CXX_STANDARD_REQUIRED <span class="keyword">True</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 控制动静态库生成目录,这样在windows上不用考虑运行时路径问题</span></span><br><span class="line"><span class="comment"># we don't need to tinker with the path to run the executable</span></span><br><span class="line"><span class="keyword">set</span>(CMAKE_ARCHIVE_OUTPUT_DIRECTORY <span class="string">"$&#123;PROJECT_BINARY_DIR&#125;"</span>)</span><br><span class="line"><span class="keyword">set</span>(CMAKE_LIBRARY_OUTPUT_DIRECTORY <span class="string">"$&#123;PROJECT_BINARY_DIR&#125;"</span>)</span><br><span class="line"><span class="keyword">set</span>(CMAKE_RUNTIME_OUTPUT_DIRECTORY <span class="string">"$&#123;PROJECT_BINARY_DIR&#125;"</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">option</span>(BUILD_SHARED_LIBS <span class="string">"Build using shared libraries"</span> <span class="keyword">ON</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 配置头文件, 将一些CMake属性值保存到源代码中</span></span><br><span class="line"><span class="keyword">configure_file</span>(TutorialConfig.h.in TutorialConfig.h)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 添加自定义数学库</span></span><br><span class="line"><span class="keyword">add_subdirectory</span>(MathFunctions)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 生成执行程序</span></span><br><span class="line"><span class="keyword">add_executable</span>(Tutorial tutorial.cxx)</span><br><span class="line"><span class="keyword">target_link_libraries</span>(Tutorial PUBLIC MathFunctions)</span><br></pre></td></tr></table></figure>

<p><strong>MathFunctions/CMakeLists.txt</strong>更改如下:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 生成运行时需要的动态库</span></span><br><span class="line"><span class="keyword">add_library</span>(MathFunctions MathFunctions.cxx)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 通过INTERFACE向使用者传播头文件搜索路径</span></span><br><span class="line"><span class="keyword">target_include_directories</span>(MathFunctions</span><br><span class="line">                           INTERFACE <span class="variable">$&#123;CMAKE_CURRENT_SOURCE_DIR&#125;</span></span><br><span class="line">                           )</span><br><span class="line"></span><br><span class="line"><span class="comment"># 是否使用自定义数学库</span></span><br><span class="line"><span class="keyword">option</span>(USE_MYMATH <span class="string">"Use tutorial provided math implementation"</span> <span class="keyword">ON</span>)</span><br><span class="line"><span class="keyword">if</span>(USE_MYMATH)</span><br><span class="line">  <span class="comment"># 数学库目标宏定义</span></span><br><span class="line">  <span class="keyword">target_compile_definitions</span>(MathFunctions PRIVATE <span class="string">"USE_MYMATH"</span>)</span><br><span class="line"></span><br><span class="line">  <span class="comment"># 首先生成一个用于产生预定义值表源代码的执行程序</span></span><br><span class="line">  <span class="keyword">add_executable</span>(MakeTable MakeTable.cxx)</span><br><span class="line"></span><br><span class="line">  <span class="comment"># 添加自定义命令以产生源代码(依赖于MakeTable目标)</span></span><br><span class="line">  <span class="keyword">add_custom_command</span>(</span><br><span class="line">    OUTPUT <span class="variable">$&#123;CMAKE_CURRENT_BINARY_DIR&#125;</span>/Table.h</span><br><span class="line">    <span class="keyword">COMMAND</span> MakeTable <span class="variable">$&#123;CMAKE_CURRENT_BINARY_DIR&#125;</span>/Table.h</span><br><span class="line">    DEPENDS MakeTable</span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line">  <span class="comment"># 生成仅进行sqrt计算的静态库</span></span><br><span class="line">  <span class="keyword">add_library</span>(SqrtLibrary STATIC</span><br><span class="line">              mysqrt.cxx</span><br><span class="line">              <span class="variable">$&#123;CMAKE_CURRENT_BINARY_DIR&#125;</span>/Table.h</span><br><span class="line">              )</span><br><span class="line"></span><br><span class="line">  <span class="comment"># 通过PRIVATE定义目标内部使用头文件搜索路径</span></span><br><span class="line">  <span class="comment"># Table.h文件生成在$&#123;CMAKE_CURRENT_BINARY_DIR&#125;中</span></span><br><span class="line">  <span class="keyword">target_include_directories</span>(SqrtLibrary PRIVATE</span><br><span class="line">                             <span class="variable">$&#123;CMAKE_CURRENT_BINARY_DIR&#125;</span></span><br><span class="line">                             )</span><br><span class="line"></span><br><span class="line">  <span class="comment"># 设置SqrtLibrary目标属性: 如果默认生成共享库, 需要将PIC(POSITION_INDEPENDENT_CODE)设置为True</span></span><br><span class="line">  <span class="keyword">set_target_properties</span>(SqrtLibrary PROPERTIES</span><br><span class="line">                        POSITION_INDEPENDENT_CODE <span class="variable">$&#123;BUILD_SHARED_LIBS&#125;</span></span><br><span class="line">                        )</span><br><span class="line"></span><br><span class="line">  <span class="comment"># 将数学库链接到自定义sqrt库</span></span><br><span class="line">  <span class="keyword">target_link_libraries</span>(MathFunctions PRIVATE SqrtLibrary)</span><br><span class="line"><span class="keyword">endif</span>()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 定义目标宏用于在windows上设置动态库标志declspec(dllexport)</span></span><br><span class="line"><span class="keyword">target_compile_definitions</span>(MathFunctions PRIVATE <span class="string">"EXPORTING_MYMATH"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装规则</span></span><br><span class="line"><span class="keyword">install</span>(TARGETS MathFunctions DESTINATION lib)</span><br><span class="line"><span class="keyword">install</span>(FILES MathFunctions.h DESTINATION <span class="keyword">include</span>)</span><br></pre></td></tr></table></figure>

<p><strong>MathFunctions/MathFunctions.h</strong>使用dll导出(dll export)定义:</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">if</span> defined(_WIN32)</span></span><br><span class="line"><span class="meta">#  <span class="meta-keyword">if</span> defined(EXPORTING_MYMATH)</span></span><br><span class="line"><span class="meta">#    <span class="meta-keyword">define</span> DECLSPEC __declspec(dllexport)</span></span><br><span class="line"><span class="meta">#  <span class="meta-keyword">else</span></span></span><br><span class="line"><span class="meta">#    <span class="meta-keyword">define</span> DECLSPEC __declspec(dllimport)</span></span><br><span class="line"><span class="meta">#  <span class="meta-keyword">endif</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">else</span> <span class="comment">// non windows</span></span></span><br><span class="line"><span class="meta">#  <span class="meta-keyword">define</span> DECLSPEC</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> mathfunctions &#123;</span><br><span class="line"><span class="function"><span class="keyword">double</span> DECLSPEC <span class="title">sqrt</span><span class="params">(<span class="keyword">double</span> x)</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>其它对C++代码的修改见<a href="https://cmake.org/cmake/help/latest/guide/tutorial/index.html" target="_blank" rel="noopener">CMake教程</a></p>
<h4 id="命令行使用示例-4"><a href="#命令行使用示例-4" class="headerlink" title="命令行使用示例"></a>命令行使用示例</h4><p>在项目目录下</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">$ mkdir build</span><br><span class="line">$ cd build</span><br><span class="line">$ cmake ..</span><br><span class="line">$ cmake --build .</span><br><span class="line"></span><br><span class="line">  Checking Build System</span><br><span class="line">  Building Custom Rule E:&#x2F;Help&#x2F;Other&#x2F;CMake&#x2F;CMake_Tutorial&#x2F;guide&#x2F;tutorial&#x2F;Step10&#x2F;MathFunctions&#x2F;CMakeLists.txt</span><br><span class="line">  MakeTable.cxx</span><br><span class="line">  MakeTable.vcxproj -&gt; E:\Help\Other\CMake\CMake_Tutorial\guide\tutorial\Step10\build\Debug\MakeTable.exe</span><br><span class="line">  Generating Table.h</span><br><span class="line">  Building Custom Rule E:&#x2F;Help&#x2F;Other&#x2F;CMake&#x2F;CMake_Tutorial&#x2F;guide&#x2F;tutorial&#x2F;Step10&#x2F;MathFunctions&#x2F;CMakeLists.txt</span><br><span class="line">  mysqrt.cxx</span><br><span class="line">  SqrtLibrary.vcxproj -&gt; E:\Help\Other\CMake\CMake_Tutorial\guide\tutorial\Step10\build\Debug\SqrtLibrary.lib</span><br><span class="line">  Building Custom Rule E:&#x2F;Help&#x2F;Other&#x2F;CMake&#x2F;CMake_Tutorial&#x2F;guide&#x2F;tutorial&#x2F;Step10&#x2F;MathFunctions&#x2F;CMakeLists.txt</span><br><span class="line">  MathFunctions.cxx</span><br><span class="line">    正在创建库 E:&#x2F;Help&#x2F;Other&#x2F;CMake&#x2F;CMake_Tutorial&#x2F;guide&#x2F;tutorial&#x2F;Step10&#x2F;build&#x2F;Debug&#x2F;MathFunctions.lib 和对象 E:&#x2F;Help&#x2F;Other&#x2F;CMake&#x2F;CMake_Tutorial&#x2F;guide&#x2F;tutorial&#x2F;St</span><br><span class="line">  ep10&#x2F;build&#x2F;Debug&#x2F;MathFunctions.exp</span><br><span class="line">  MathFunctions.vcxproj -&gt; E:\Help\Other\CMake\CMake_Tutorial\guide\tutorial\Step10\build\Debug\MathFunctions.dll</span><br><span class="line">  Building Custom Rule E:&#x2F;Help&#x2F;Other&#x2F;CMake&#x2F;CMake_Tutorial&#x2F;guide&#x2F;tutorial&#x2F;Step10&#x2F;CMakeLists.txt</span><br><span class="line">  tutorial.cxx</span><br><span class="line">  Tutorial.vcxproj -&gt; E:\Help\Other\CMake\CMake_Tutorial\guide\tutorial\Step10\build\Debug\Tutorial.exe</span><br><span class="line">  Building Custom Rule E:&#x2F;Help&#x2F;Other&#x2F;CMake&#x2F;CMake_Tutorial&#x2F;guide&#x2F;tutorial&#x2F;Step10&#x2F;CMakeLists.txt</span><br></pre></td></tr></table></figure>


<h3 id="10-生成器表达式-条件判断"><a href="#10-生成器表达式-条件判断" class="headerlink" title="10. 生成器表达式,条件判断"></a>10. 生成器表达式,条件判断</h3><p>在上一步的基础上, 本节示例展示了:</p>
<ul>
<li>在构建过程中计算生成器表达式值，以生成特定于每个构建配置的信息</li>
<li>生成器表达式有三类: 逻辑表达式、信息表达式和输出表达式(Logical, Informational, and Output expressions)</li>
<li>逻辑表达式: <code>$&lt;0:...&gt;</code>的结果是空字符串，<code>$&lt;1:...&gt;</code>的结果是“…”的内容。它们也可以嵌套。</li>
<li>生成器表达式通常用来按需添加编译标志</li>
<li>使用<strong>INTERFACE目标</strong>在目标间传递属性</li>
</ul>
<blockquote>
<p>注: 本节示例初始代码在示例目录的<code>Step10</code>子目录, 成果在<code>Step11</code>子目录</p>
</blockquote>
<h4 id="核心代码更改-7"><a href="#核心代码更改-7" class="headerlink" title="核心代码更改"></a>核心代码更改</h4><p><strong>顶层CMakeLists.txt</strong>的相应部分:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># specify the C++ standard</span></span><br><span class="line"><span class="keyword">set</span>(CMAKE_CXX_STANDARD <span class="number">11</span>)</span><br><span class="line"><span class="keyword">set</span>(CMAKE_CXX_STANDARD_REQUIRED <span class="keyword">True</span>)</span><br></pre></td></tr></table></figure>
<p>更改为:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">add_library</span>(tutorial_compiler_flags INTERFACE)</span><br><span class="line"><span class="keyword">target_compile_features</span>(tutorial_compiler_flags INTERFACE cxx_std_11)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 通过BUILD_INTERFACE生成器表达式添加编译器警告标志</span></span><br><span class="line"><span class="keyword">set</span>(gcc_like_cxx <span class="string">"$&lt;COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU&gt;"</span>)</span><br><span class="line"><span class="keyword">set</span>(msvc_cxx <span class="string">"$&lt;COMPILE_LANG_AND_ID:CXX,MSVC&gt;"</span>)</span><br><span class="line"><span class="keyword">target_compile_options</span>(tutorial_compiler_flags INTERFACE</span><br><span class="line">  <span class="string">"$&lt;$&#123;gcc_like_cxx&#125;:$&lt;BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused&gt;&gt;"</span></span><br><span class="line">  <span class="string">"$&lt;$&#123;msvc_cxx&#125;:$&lt;BUILD_INTERFACE:-W3&gt;&gt;"</span></span><br><span class="line">)</span><br></pre></td></tr></table></figure>

<p><strong>库目录CMakeLists.txt</strong>目标链接库代码:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">target_link_libraries</span>(MakeTable[SqrtLibrary|MathFunctions] PRIVATE[PUBLIC] tutorial_compiler_flags)</span><br></pre></td></tr></table></figure>

<h3 id="11-添加导出配置-以支持find-package"><a href="#11-添加导出配置-以支持find-package" class="headerlink" title="11. 添加导出配置,以支持find_package"></a>11. 添加导出配置,以支持find_package</h3><p>在上一步的基础上, 本节示例展示了:</p>
<ul>
<li>如何让其他项目方便地使用本项目</li>
<li>在<strong>install(TARGETS)</strong>中使用<strong>EXPORT</strong>关键字, 它用于将目标从安装树导入到另一个项目</li>
<li>生成<strong>MathFunctionsConfig.cmake</strong>, 以让<a href="https://cmake.org/cmake/help/latest/command/find_package.html#command:find_package" target="_blank" rel="noopener">find_package()</a>命令可以找到本项目</li>
<li>显式安装生成的<strong>MathFunctionsTargets.cmake</strong></li>
</ul>
<blockquote>
<p>注: 本节示例初始代码在示例目录的<code>Step11</code>子目录, 成果在<code>Step12</code>子目录</p>
</blockquote>
<h4 id="核心代码更改-8"><a href="#核心代码更改-8" class="headerlink" title="核心代码更改"></a>核心代码更改</h4><p>在<strong>MathFunctions/CMakeLists.txt</strong>中增加<strong>EXPORT</strong>:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 根据项目内与安装方式包含不同的头文件目录</span></span><br><span class="line"><span class="keyword">target_include_directories</span>(MathFunctions</span><br><span class="line">                           INTERFACE</span><br><span class="line">                            $&lt;BUILD_INTERFACE:<span class="variable">$&#123;CMAKE_CURRENT_SOURCE_DIR&#125;</span>&gt;</span><br><span class="line">                            $&lt;INSTALL_INTERFACE:<span class="keyword">include</span>&gt;</span><br><span class="line">                           )</span><br><span class="line"></span><br><span class="line"><span class="comment"># 此处省略其他代码...</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装规则</span></span><br><span class="line"><span class="keyword">install</span>(TARGETS MathFunctions tutorial_compiler_flags</span><br><span class="line">        DESTINATION lib</span><br><span class="line">        <span class="keyword">EXPORT</span> MathFunctionsTargets)</span><br><span class="line"><span class="keyword">install</span>(FILES MathFunctions.h DESTINATION <span class="keyword">include</span>)</span><br></pre></td></tr></table></figure>

<p>在顶层目录中添加<strong>Config.cmake.in</strong>, 用来生成<strong>MathFunctionsTargets.cmake</strong>:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">@PACKAGE_INIT@</span><br><span class="line"></span><br><span class="line"><span class="keyword">include</span> ( <span class="string">"$&#123;CMAKE_CURRENT_LIST_DIR&#125;/MathFunctionsTargets.cmake"</span> )</span><br></pre></td></tr></table></figure>


<p>在<strong>顶层CMakeLists.txt</strong>，为了正确配置和安装<strong>MathFunctionsTargets.cmake</strong>, 添加以下内容:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">install</span>(<span class="keyword">EXPORT</span> MathFunctionsTargets</span><br><span class="line">  <span class="keyword">FILE</span> MathFunctionsTargets.cmake</span><br><span class="line">  DESTINATION lib/cmake/MathFunctions</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="keyword">include</span>(CMakePackageConfigHelpers)</span><br><span class="line"><span class="comment"># generate the config file that is includes the exports</span></span><br><span class="line">configure_package_config_file(<span class="variable">$&#123;CMAKE_CURRENT_SOURCE_DIR&#125;</span>/Config.cmake.in</span><br><span class="line">  <span class="string">"$&#123;CMAKE_CURRENT_BINARY_DIR&#125;/MathFunctionsConfig.cmake"</span></span><br><span class="line">  INSTALL_DESTINATION <span class="string">"lib/cmake/example"</span></span><br><span class="line">  NO_SET_AND_CHECK_MACRO</span><br><span class="line">  NO_CHECK_REQUIRED_COMPONENTS_MACRO</span><br><span class="line">  )</span><br><span class="line"><span class="comment"># generate the version file for the config file</span></span><br><span class="line">write_basic_package_version_file(</span><br><span class="line">  <span class="string">"$&#123;CMAKE_CURRENT_BINARY_DIR&#125;/MathFunctionsConfigVersion.cmake"</span></span><br><span class="line">  VERSION <span class="string">"$&#123;Tutorial_VERSION_MAJOR&#125;.$&#123;Tutorial_VERSION_MINOR&#125;"</span></span><br><span class="line">  COMPATIBILITY AnyNewerVersion</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment"># install the configuration file</span></span><br><span class="line"><span class="keyword">install</span>(FILES</span><br><span class="line">  <span class="variable">$&#123;CMAKE_CURRENT_BINARY_DIR&#125;</span>/MathFunctionsConfig.cmake</span><br><span class="line">  DESTINATION lib/cmake/MathFunctions</span><br><span class="line">  )</span><br></pre></td></tr></table></figure>

<p>到这里，这是一个可以在项目安装或打包以后重定位的CMake配置。 如果需要项目在一个构建目录中使用，在顶层<strong>CMakeLists.txt</strong>的结尾添加以下内容:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span>(<span class="keyword">EXPORT</span> MathFunctionsTargets</span><br><span class="line">  <span class="keyword">FILE</span> <span class="string">"$&#123;CMAKE_CURRENT_BINARY_DIR&#125;/MathFunctionsTargets.cmake"</span></span><br><span class="line">)</span><br></pre></td></tr></table></figure>

<blockquote>
<p>通过这个导出调用，我们现在生成一个<code>Targets.cmake</code>，使得在构建目录中配置生成的<code>MathFunctionsConfig.cmake</code>可以被其他项目使用，而不需要安装它。<br>此处未试验, 不理解</p>
</blockquote>
<h3 id="12-将调试版和发行版打包在一起"><a href="#12-将调试版和发行版打包在一起" class="headerlink" title="12. 将调试版和发行版打包在一起"></a>12. 将调试版和发行版打包在一起</h3><p>在上一步的基础上, 本节示例展示了:</p>
<ul>
<li>为调试版文件设置后缀: 非执行程序目标会根据<strong>CMAKE_DEBUG_POSTFIX</strong>生成它的<strong><CONFIG>_POSTFIX</strong></li>
<li>执行程序目录的<strong>DEBUG_POSTFIX</strong>需要手工设置</li>
</ul>
<blockquote>
<p>注1: 本节示例初始代码在示例目录的<code>Step12</code>子目录, 成果在<code>Complete</code>子目录<br>注2: 本节打包工作在win10上没有成功</p>
</blockquote>
<h4 id="核心代码更改-9"><a href="#核心代码更改-9" class="headerlink" title="核心代码更改"></a>核心代码更改</h4><p>在<strong>顶层CMakeLists.txt</strong>中更改:</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 设置非可执行程序目标的调试后缀</span></span><br><span class="line"><span class="keyword">set</span>(CMAKE_DEBUG_POSTFIX d)</span><br><span class="line">...</span><br><span class="line"><span class="comment"># 设置可执行程序目标的调试后缀</span></span><br><span class="line"><span class="keyword">set_target_properties</span>(Tutorial PROPERTIES DEBUG_POSTFIX <span class="variable">$&#123;CMAKE_DEBUG_POSTFIX&#125;</span>)</span><br></pre></td></tr></table></figure>



      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  


  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">老树</p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">5</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
  </nav>
</div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">老树</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://muse.theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Muse</a> 强力驱动
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/muse.js"></script>


<script src="/js/next-boot.js"></script><!-- hexo-inject:begin --><!-- hexo-inject:end -->




  















  

  

  

</body>
</html>
